function clone(object){
    function F(){}
    F.prototype = object;
    return new F;
}

/**
 * Constants For those values that should be set once and don't change.
 */
Constants = (function(){
    return {
       closedDrawer: 25,
       standardDrawer: $("#drawer").width() || 205,
       fullDrawer: 510,
//     minDragWidth: 200,        // currently unused
       minHeightDelta: .01,
       svgPath: "/templates/drawer/tabs/svg/",
       archiveThumbBuffer: {'width':5,'height':25},
       navbarCalcWidth: 1280,
//     customTracker: false,     // currently unused
       schedulerInterval: 100
    }
})();

/**
 * Globals For those values that can be changed and used in many places.
 */
Globals = (function(){
    return {
       minWindowWidth: 950,
       zoomInFactor: 2
    }
})();

/* */
/* ViewHelper */
/* */

ViewHelper = (function(){
  var dialog_iframe_template = '<div class="dialog_iframe"><div id="#{iframe_id}_parent"><iframe id="#{iframe_id}" src="#{src}" height="#{height}" width="#{width}" frameborder="0" scrolling="auto"></iframe></div></div>';

  var dialog_wrapper_template = '<div id="#{element_id}" class="dialog#{theme}"><div class="hd#{theme}"><div class="c#{theme}"/></div><div class="bd#{theme}"><div class="c#{theme}"><div class="s#{theme}">#{content}<br clear="all" style="display:none;" /></div></div></div><div class="ft#{theme}"><div class="c#{theme}"/></div></div>';
  var $ = jQuery;
  var dialog_defaults = {
    height:"auto",
    width:600,
    modal:false,
    resizable:false,
    draggable:false,
    show:0,
    cache:true,
    close: function(e,ui){
        var that = $(this);
        that.css('display','none');
        setTimeout(function(){
            delete PageElements.dialogs[that.attr("creator")];
            that.dialog('destroy').remove();
            ViewHelper.setupKeyFunctions();
            PageView.enableButtons();
        },200);
    }
  };

  var popup_defaults = {
    height: 400,
    width: 600,
    left: 400,
    top: 200,
    resizable: "yes",
    scrollbars: "yes",
    toolbar: "no",
    location: "no",
    directories: "no",
    status: "no",
    menubar: "no",
    copyhistory: "no"
  };

  var modal = '';
  var modalOverride = '';
  var isCtrl = false;
  var last_x = 0;
  var last_y = 0;

  return {
    dataSwitchError : function(XMLHttpRequest, textStatus, errorThrown){
         Console.error("Error processing XMLHttpRequest. Logging ajax options object, XMLHttpRequest object, textstatus and errorThrown");
         Console.error(this);
         Console.error(XMLHttpRequest);
         Console.error("textStatus: "+textStatus);
         Console.error("errorThrown: "+errorThrown);
    },

    schedule : function(functions, context, wait_interval){
        var timerInterval = wait_interval || Constants.schedulerInterval;
        setTimeout(function(){
            var process = functions.shift();
            if(!process){
                Console.log("Error in schedule, check call format");
                //return false;
            }else{
               process.call(context);
            }
            if (functions.length > 0){
                setTimeout(arguments.callee, timerInterval);
            }
        }, timerInterval);
    },

    pad : function(number, length) {
        var str = '' + number;
            while (str.length < length) {
            str = '0' + str;
        }
        return str;
    },

    cancelKeyFunctions: function(element){
      $(document).unbind('keydown.key_controls',ViewHelper.documentKeyDown);
      $(document).unbind('keyup.key_controls',ViewHelper.documentKeyUp);
    },

    getHiddenImageDimensions: function(parent_element){
        var rand_text = ViewHelper.randomText();
        var tmp_elem = parent_element.clone();
        var imgs = tmp_elem.find("img");
        Constants[rand_text] = {'width':0,'height':0};
        imgs.filter(":first").load(function(){
            var tmp_obj = {'width':0,'height':0};
            for(var i = 0; i < imgs.length; i++){
                var tmp_w = $(imgs[i]).get(0).width || 0;
                var tmp_h = $(imgs[i]).get(0).height || 0;
                if(tmp_w > tmp_obj.width){
                    tmp_obj.width = tmp_w;
                }
                if(tmp_h > tmp_obj.height){
                    tmp_obj.height = tmp_h;
                }
                if(i==(imgs.length-1)){
                    Constants[rand_text] = tmp_obj;
                    tmp_elem.remove();
                }
            }
        });
        tmp_elem.css({position:"absolute",left:"-1000px",display:"block",visibility:"hidden"}).appendTo("body");
        setTimeout(function(){
            tmp_elem.remove();
        },5000)
        return rand_text;
    },

    setupSprite: function (parent) {
      var currentBrowser = navigator.userAgent.toLowerCase();
      if (currentBrowser.indexOf("msie 6") != -1){
                $("#" + parent + " span[class*='icon']").each(
                    function(){
                        var src = $(this).css("background-image");
                        src = src.substring(src.indexOf("/images"), src.length-1);
                        if(src.length > 3){
                        $(this).css("backgroundImage", "none");
                        $(this).css("filter", "progid:DXImageTransform.Microsoft.AlphaImageLoader(src="+src+")");
                    }
                });
                $("#" + parent + " img[src*='.png']").each(function(){
                    var that = $(this);
                    var src = that.attr('src');
                    var dims = {
                        'width':that.width(),
                        'height':that.height()
                    };
                    if(dims.width == 0 || dims.height == 0){
                        var tmp_img_obj = ViewHelper.getHiddenImageDimensions(that.parent());
                var tmp_interval = setInterval(function(){
                    if(typeof Constants[tmp_img_obj] != "undefined" && Constants[tmp_img_obj]["height"] > 0){
                        ViewHelper.completeSprite(that,src,Constants[tmp_img_obj].width,Constants[tmp_img_obj].height);
                        delete Constants[tmp_img_obj];
                        clearInterval(tmp_interval);
                            }
                        },500);
                    }else{
                        ViewHelper.completeSprite(that,src,dims.width,dims.height);
                    }
        });
      }
    },

    completeSprite: function(img,src,width,height){
            img.css({
           "filter":"progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled='true', sizingMethod='crop',src="+src+")",
           "height":height+"px",
           "width":width+"px",
           "disabled":"true",
           "display":"block"})
            img.attr('src','/images/misc/clear.gif');
    },

    enableTransparentPngs: function(element){
        if($.browser.msie && /MSIE 6.0/.test(navigator.userAgent)){
            $("img[src$='png']").each(function(){
                var src = $(this).attr('src');
                var width = $(this).width();
                var height = $(this).height();
                ViewHelper.completeSprite($(this),src,width,height)
            });
        }
    },

    documentKeyDown : function(e){
            if (e.target && e.target.type && e.target.type == 'text') {
                // pass through text editing keystrokes
                return;
            }
        if (e.which == 39) {
          // right arrow
         var scroll_target = $.browser.safari ? $("body") : $("html");
         last_x = scroll_target.scrollLeft();
         setTimeout("ViewHelper.getScrollXPos(false)",100);
         return;
        } else if (e.which == 37) {
          // left arrow
         scroll_target = $.browser.safari ? $("body") : $("html");
         last_x = scroll_target.scrollLeft();
         setTimeout("ViewHelper.getScrollXPos(true)",100);
         return;
        } else if (e.which == 40 || e.which == 34) {
         // down arrow, page down
         scroll_target = $.browser.safari ? $("body") : $("html");
         last_y = scroll_target.scrollTop();
         setTimeout("ViewHelper.getScrollYPos(false)",100);
         return;
        } else if (e.which == 38 || e.which == 33) {
         // up arrow, page up
         scroll_target = $.browser.safari ? $("body") : $("html");
         last_y = scroll_target.scrollTop();
         setTimeout("ViewHelper.getScrollYPos(true)",100);
         return;
        } else if (e.which == 36) {
          // home
          PageController.handleGoToPage(1);
          return false;
        } else if (e.which == 35) {
          // end

          PageController.handleGoToPage(PageModel.lastPage);
          return false;
        } else if (e.which == 17 || e.which == 224){
          // ctrl key -> set flag
            isCtrl = true;
        } else if (e.which == 70 && isCtrl) {
          // ctrl+f -> open search
            e.preventDefault();
            e.stopPropagation();
            PageElements.tabs[0].tabs('select','searchResults');
        }else if (e.which == 80 && isCtrl) {
          // ctrl+p ->open print
            e.preventDefault();
            e.stopPropagation();
            $("#button_link_print",Navbar.Model.navbar).trigger('click');
        }else if (e.which == 83 && isCtrl) {
          // ctrl+s -> open share
            e.preventDefault();
            e.stopPropagation();
            $("#button_link_share",Navbar.Model.navbar).trigger('click');
        }else if (e.which == 90 && isCtrl) {
          // ctrl+z -> open zoom
            e.preventDefault();
            e.stopPropagation();
            $("#button_link_zoom",Navbar.Model.navbar).trigger('click');
        }else if (e.which == 107 && Offline.isOffline()===false && Offline.downloadInProgress===false){
          // + key -> zoom in one level
            var zoom_levels = PageModel.zoomLevels;
            var current_zoom_number = PageModel.zoomIndex;
            if(current_zoom_number < (zoom_levels.length-1)){
                var new_zoom_preference = "width:"+zoom_levels[current_zoom_number+1]["width"]+"&height:"+zoom_levels[current_zoom_number+1]["height"];
                PageView.zoomChange(current_zoom_number+1);
                if(PageView.getAutoZoom()){
                    PageView.setAutoZoom(false);
                }
                CookieManager.set(
                    "preference_zoom",
                    new_zoom_preference
                );
                PageModel.zoomPreference = new_zoom_preference;
            }
        }else if (e.which == 109 && Offline.isOffline()===false && Offline.downloadInProgress===false){
          // - key -> zoom out one level
            current_zoom_number = PageModel.zoomIndex;
            if(current_zoom_number != 0){
                zoom_levels = PageModel.zoomLevels;
                new_zoom_preference = "width:"+zoom_levels[current_zoom_number-1]["width"]+"&height:"+zoom_levels[current_zoom_number-1]["height"];
                PageView.zoomChange(current_zoom_number-1);
                if(PageView.getAutoZoom()){
                    PageView.setAutoZoom(false);
                }
                CookieManager.set(
                    "preference_zoom",
                    new_zoom_preference
                );
                PageModel.zoomPreference = new_zoom_preference;
            }
        }
    },

    documentKeyUp : function(e){
        if (e.which == 17 || e.which == 224){
          // remove ctrl key flag
            isCtrl = false;
        }
    },

    setupKeyFunctions: function(){
      $(document).bind('keydown.key_controls',ViewHelper.documentKeyDown).bind('keyup.key_controls',ViewHelper.documentKeyUp);
    },

    getScrollYPos : function(prev) {
      var scroll_target = $.browser.safari ? $("body") : $("html");
      if (last_y == scroll_target.scrollTop()) {
         if (prev) {
            PageController.handlePrevPage();
         } else {
            PageController.handleNextPage();
         }
      }
    },

    getScrollXPos : function(prev) {
      var scroll_target = $.browser.safari ? $("body") : $("html");
      if (last_x == scroll_target.scrollLeft()) {
         if (prev) {
            PageController.handlePrevPage();
         } else {
            PageController.handleNextPage();
         }
      }
    },

    accordion: function(element){
          return $("div.accordionify",element).accordion({header: 'h3',alwaysOpen:false,active:false,clearStyle: true,autoHeight: false});
      },

      tabs: function(element){
        var tabs = $("ul.tabify",element);
        if(tabs.length > 0){
          $(tabs).tabs();
        }
    },

    openHoverDialog: function(link){
      ViewHelper.openDialog(link,ViewHelper.dialogMouseBehaviors);
      PageElements.dialogs[$(link).attr("id")]["link_active"]=true;
    },

    handleHoverDialogLinkHoverOver: function(){
        var that = this;
        var link_id = $(that).attr("id");
        if(!PageElements.dialogs[link_id]){
            ViewHelper.openHoverDialog(that);
        }else{
            PageElements.dialogs[link_id]["link_active"]=true;
        }
    },

    handleHoverDialogLinkHoverOut: function(){
        var that = this;
        var link_id = $(that).attr("id");
        if(PageElements.dialogs[link_id]){
            PageElements.dialogs[link_id]["link_active"] = false;
        }
    },

    dialogMouseBehaviors: function(e,ui){
      var that = this;
      var creator = $(that).attr("creator");
      $(that).parent().bind("mouseover",function(){
          PageElements.dialogs[creator]["dialog_active"]=true;
      });
      $(that).parent().bind("mouseleave",function(){
          PageElements.dialogs[creator]["dialog_active"]=false;
          setTimeout(function(){
              if(PageElements.dialogs[creator] && PageElements.dialogs[creator]["link_active"]==false){
                  $(that).dialog("close");
              }
          },500);
      });
    },

    setDialogModalOverride: function(state){
        if(ViewHelper.trueTypeOf(state) == "boolean"){
            modalOverride = state;
        }
    },

    removeDialogCloseButton: function(dialog){
        dialog.prev(".ui-dialog-titlebar").children(".ui-dialog-titlebar-close").remove();
    },

    openDialog: function(link,open_callback){
        var dialog_element;
        var link_id = $(link).attr("id");
        if(!link_id){
          link_id = ViewHelper.randomText();
          $(link).attr("id",link_id);
        }
        var content_location = $(link).attr("href");
        var dialog_options = ViewHelper.combineOptions(ViewHelper.csvToObj($(link).attr("type")),dialog_defaults);

        if(typeof PageElements.dialogs[link_id]!='undefined'){
            ViewHelper.closeAllDialogs();
            return;
        }
        ViewHelper.closeAllDialogs();
        ViewHelper.cancelKeyFunctions();

        if($(link).attr("title") && dialog_options["title"]!==false){
          dialog_options["title"] = $(link).attr("title");
        }
        modal = dialog_options['modal'];
        if(open_callback){
          dialog_options["custom_open_callback"] = open_callback;
        }

      if(dialog_options["anchor"] == true){
            dialog_options["dialogClass"] = "anchored";
          var link_offset = $(link).offset();
          var link_width = $(link).width();
          var navbar_offset = $("#navbar_pagination_wrapper").offset();
          var navbar_width = $("#navbar_pagination_wrapper").width();
          var dialog_left = 0;
          var bg_top = 0;
          var scroll_left = $(window).scrollLeft();
          var screen_offset_left = link_offset.left-scroll_left;
          if(screen_offset_left < (dialog_options["width"]/2 + 10)){
            dialog_left = screen_offset_left * .25;
            dialog_options["background_position"] = (link_width/2) + "px "+bg_top+"px";
          }else if((link_offset.left + (dialog_options["width"]/2) + link_width) > (navbar_offset.left + navbar_width)){
            var bump = (link_offset.left + (dialog_options["width"]/2) + (link_width/2)) - (navbar_offset.left + navbar_width) + 10;
            dialog_left = screen_offset_left - (dialog_options["width"]/2) - bump;
            dialog_options["background_position"] = (dialog_options["width"]/2 + bump + (link_width/2) - 15) + "px "+bg_top+"px";
          }else{
            dialog_left = (screen_offset_left - (dialog_options["width"]/2) + (link_width/2));
            dialog_options["background_position"] = "center "+bg_top+"px";
          }
          var dialog_top = (ViewHelper.height($(link))-1);
          dialog_options["position"] = [dialog_left,dialog_top];
      }


      if(content_location.match(/^(http|https):\/\//)&& !content_location.match(document.domain)){
        //If the url is from an outside domain, we're going to use an iframe
        var iframe_template = new Template(dialog_iframe_template);
        var data = iframe_template.evaluate({
          iframe_id:$(link).attr("id") + "_iframe",
          src: content_location,
          width:dialog_options["width"],
          height:dialog_options["height"]-20}
        );
        $(data).appendTo("body").dialog(dialog_options);
      }else{
        dialog_options.open = ViewHelper.ajaxDialogOpenCallback;
        dialog_options.url = content_location;
        dialog_options.dialog_id = link_id + "_dialog";
        dialog_options.content_id = link_id + "_content";
        dialog_options.creator = link_id;
        ViewHelper.ajaxDialogLoad(dialog_options);
      }
      if(typeof Tracker != "undefined"){
        var tracking_location = ViewHelper.formatTrackingUrl(content_location);
        var tracking_options = {"pageName":document.location.protocol + "//" + document.location.host + tracking_location};
        tracking_options["category"] = "dialog";
        if (dialog_options["title"]){
          tracking_options["title"] = dialog_options["title"];
          tracking_options["dialog_type"] = dialog_options["title"];
        } else if (dialog_options["dialog_id"]){
            tracking_options["dialog_type"] = dialog_options["dialog_id"];
        } else {
          tracking_options["dialog_type"] = "unknown";
        }
        tracking_options["lochref"] = document.location.href;
          setTimeout(function(){
              Tracker.trackPage(tracking_options);
          },0);
      }

    },

    ajaxDialogLoad: function(dialog_options){
        var tmp_height = dialog_options.height+"px";
        var tmp_padding = (dialog_options.height/2)+"px";
        dialog_options.height = "auto";
        var dialog_element = $(ViewHelper.shadowWrap("<div id=\""+dialog_options.content_id+"\" style=\"height:"+tmp_height+";\">&nbsp;</div>",dialog_options["custom_theme"])).appendTo("body").dialog(dialog_options);

        ViewHelper.tabs(dialog_element); //commented out until JQuery 1.3...we don't use it and this is slow in IE6
        $(dialog_element).hover(PageView.disableButtons,PageView.enableButtons);
        if(dialog_options["anchor"] == true){
            dialog_element.parents('div.anchored').css("background-position", dialog_options.background_position);
        };
        dialog_element.attr("creator",dialog_options.creator).attr("id",dialog_options.dialog_id);
        PageElements.dialogs[dialog_options.creator] = {
            'id':dialog_options.dialog_id,
            'link_active':true,
            'dialog_active':false
        };
    },

    ajaxDialogOpenCallback: function(e,ui){
        if(ui.options.hasOwnProperty("url")){
          DataSwitch.get({'url':ui.options.url,
            'cache': ui.options.cache,
            'success':function(data,textStatus){
                   var done = false;
                   var needs_accordion = data.indexOf('accordionify') != -1;
                   if(needs_accordion==false){
                       $("#"+ui.options.content_id).html(data)
                       done = true;
                   }else{
                       if(!$.browser.safari && !$.browser.opera){
                           var accordioned = ViewHelper.accordion($(data));
                           setTimeout(function(){
                               $("#"+ui.options.content_id).html(accordioned).parents("div.dialog").andSelf().css({height:"auto",minHeight:"5px"});
                               done = true;
                           },500);
                       }else{
                           ViewHelper.accordion($("#"+ui.options.content_id).html(data).parents("div.dialog").andSelf().css({height:"auto",minHeight:"5px"}));
                           done = true;
                       }
                     }
                   if(ui.options.hasOwnProperty("custom_open_callback")){
                       var custom_callback_interval = setInterval(function(){
                           if(done){
                               clearInterval(custom_callback_interval);
                               var callback = ui.options.custom_open_callback;
                               callback.call($("#"+ui.options.dialog_id)[0]);
                           }
                       },600);
                   }
            }
          });
        }
    },

    shadowWrap: function(html_content,custom_theme, custom_id){
        var template_content = typeof html_content == 'object'
                ? html_content.html()
                : html_content;
        var elem_id = custom_id || ViewHelper.randomText();
        var wrapper_template = new Template(dialog_wrapper_template);
        var wrapper_theme = (typeof custom_theme != "undefined") ? "-" + custom_theme : "";
        return wrapper_template.evaluate({
            content:template_content,
            theme: wrapper_theme,
            element_id: elem_id
        });
    },

    dialogBlur: function(event){
        if(event){
            var target = $(event.target);
            if (target.is('.ui-dialog') || target.parents('.ui-dialog').length || target.parents('#navbar_tools').length) {
                return;
            }
        }

        ViewHelper.closeAllDialogs();
    },

    closeAllDialogs: function(){
        if(modal != true && modalOverride != true){
            $.each(PageElements.dialogs,function(){
                $("#"+this.id).dialog('close');
            });
            /* commented out by ja for performance reasons...any dialog should be registered with PageElements.
               This was done as a catch-all but it's killing IE in large issues (see hemmings)
            $(".dialog, .dialog_black").each(function(){
                $(this).dialog("close");
            });*/
        }
    },

      closeHoverDialog: function(link){
        var dialog_id = $(link).attr("id");
        $("#"+PageElements.dialogs[dialog_id][dialog_id+'_dialog']).dialog("close");
        delete PageElements.dialogs[dialog_id];
      },

      openPopup: function(link){
        var content_location = $(link).attr("href");
        var window_name = '_blank';
        var popup_options = ViewHelper.rtrim(ViewHelper.printOptions(ViewHelper.combineOptions(ViewHelper.csvToObj($(link).attr("type")),popup_defaults)),",");
        window.open(content_location,window_name,popup_options);
      },

    isHidden: function(element){
      return $(element).hasClass("hidden");
    },

    csvToObj: function(options,delimiter){
      retval = {};
      delimiter = delimiter ? delimiter : ";";
      options = this.trim(options,delimiter);
      sets = options.split(delimiter);
      for (var i=0;i<sets.length;i++){
        key_val = sets[i].split("=");
        retval[key_val[0]] = key_val[1] ? this.cast(this.trim(key_val[1])) : null;
      }
      return retval;
    },

    combineOptions: function(options,defaults){
      var retval = {};
      var combined_options = [defaults,options];
      for (var i=0;i<combined_options.length;i++){
        for(var opt in combined_options[i]){
          retval[opt] = combined_options[i][opt];
        }
      }
      return retval
    },

    printOptions: function(options,delimiter){
      var retval = "";
      var delimiter = delimiter ? delimiter : ",";
        for(var opt in options){
          retval = retval + opt + "=" + options[opt] + delimiter;
        }
        return retval;
    },

    cast: function(val){
      var testInt = /^\d+$/;
      if(testInt.test(val)){
        return parseInt(val);
      }
      if ((val.charAt(0) == '[') && (val.charAt(val.length-1) == ']')) {
        val = val.substring(1,val.length-1);
        val = val.split(',');
        for (var i=0;i<val.length;i++) {
           val[i] = this.cast(val[i]);
        }
        return val;
      }
      switch(val){
        case "true":
          return true;
          break;
        case "false":
          return false;
        default:
          return val;
      }
    },

    trim: function(str, chars) {
        str = str || "";
        chars = chars || "\\s";
        return this.ltrim(this.rtrim(str, chars), chars);
    },

    ltrim: function(str, chars) {
        str = str || "";
        chars = chars || "\\s";
        return str.replace(new RegExp("^[" + chars + "]+", "g"), "");
    },

    rtrim: function(str, chars) {
        str = str || "";
        chars = chars || "\\s";
        return str.replace(new RegExp("[" + chars + "]+$", "g"), "");
    },

    randomText: function(){
      var chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz";
      var string_length = 8;
      var random_string = '';
      for (var i=0; i<string_length; i++) {
         var rnum = Math.floor(Math.random() * chars.length);
         random_string += chars.substring(rnum,rnum+1);
      }
      return random_string;
    },

    trueTypeOf: function(v) {
          if (typeof(v) == "object") {
            if (v === null) return "null";
            if (v.constructor == (new Array).constructor) return "array";
            if (v.constructor == (new Date).constructor) return "date";
            if (v.constructor == (new RegExp).constructor) return "regex";
            if (v.constructor == (new Boolean).constructor) return "boolean";
            return "object";
          }
          return typeof(v);
        },

      showHide: function(show_these,hide_these){
        var do_show = ViewHelper.trueTypeOf(show_these) || false;
        var do_hide = ViewHelper.trueTypeOf(hide_these) || false;

        function do_show_hide(type,val,display){
            switch(type){
                case "array":
                    for(i=0;i<val.length;i++){
                        $(val[i]).css("display",display);
                    }
                    break;
                case "object":
                    $(val).css("display",display);
                    break;
                case "string":
                    $(val).css("display",display)
                    break;
            }
        }

        if(do_show){
            do_show_hide(do_show,show_these,"block");
        }
        if(do_hide){
            do_show_hide(do_hide,hide_these,"none");
        }
    },

    closeDialog: function(id){
      $("#" + id).remove();
    },

    height: function(element){
      if(element == null || element.length == 0){
         return 0;
      }else{
         return $(element).height() || parseInt($(element).css('height'));
      }
    },

    width: function(element){
      if(element == null || element.length == 0){
         return 0;
      }else{
         return $(element).width() || parseInt($(element).css('width'));
      }
    },

    /**
     * Set the width of the passed in element as a style property.
     * If -1 is passed in, remove the "width" style from the element.  This
     * is designed to go back to the default value from the .css file
     *
     * @param element the DOM element to change
     * @param newWidth the width value to set.  -1 removes the property
     */
    setWidth: function(element, newWidth){
        if (newWidth == -1) {
            $(element).css("width","");
        } else {
            $(element).width(newWidth);
        }
    },

    hide: function(elements){
      $(elements).each(function(){
        if(!ViewHelper.isHidden(this)){
          $(this).addClass("hidden");
        }
      })
    },

    show: function(elements){
      $(elements).each(function(){
        if(ViewHelper.isHidden(this)){
          $(this).removeClass("hidden");
        }
      })
    },
    makeScrollable: function(element, height_constraint){
      if(typeof element == "undefined" && Drawer.View.open_tab){
          var scroll_target = $(Drawer.View.open_tab.panel);
      }else{
          var scroll_target = element;
      }
      if(scroll_target){
        new Scroller(scroll_target.attr('id'));
      }
    $("#tableOfContents ol").css("width",$("#wrapper_tableOfContents").width() - 10);
    },

    normalizeImages: function(container,options){
      w = $("img:first",container).get(0).width;
      h = $("img:first",container).get(0).height;
      needs_w = false;
      needs_h = false;
      options = options || {};
      options.width = typeof options.width != "undefined" ? options.width : true;
      options.height = typeof options.height != "undefined" ? options.height : true;
      $("img",container).each(function(){
        var this_w = this.width;
        var this_h = this.height;
        if(options.width && (w==0 || (this_w-w/w)<.15)){
            needs_w = true;
        }
        if(options.height && (h==0 || (h-this_h)/this_h<.15)){
            needs_h = true;
        }
        if(needs_w || needs_h){
          $(this).css({"height":h+"px","width":w+"px"});
        }
      });
    },

    selectedTabOpacityFix: function(direction){
        if($.browser.mozilla === true && $.browser.version.indexOf("1.8")!=-1){
            switch(direction){
                case "in":
                        $(".svgex","#main_tabs").animate({opacity:".99"});
                    break;
                default:
                        $(".svgex","#main_tabs").animate({opacity:"1"});
            }
        }
    },

    formatTrackingUrl: function(url){
        var matches = url.match(/(.*)\/([\w]+).action\??(.*)/i);
        if(matches){
            var doc_bit = matches[1];
            var action_bit = matches.length > 2 ? matches[2] : "";
            var params_bit = matches.length > 3 ? matches[3] : null;
            url = doc_bit + '?t=' + action_bit;
            if (params_bit) { url += '&' + params_bit; }
        }
        return url;
    }
  };
})();
ViewHelper.ContextMenu = {};

ViewHelper.ContextMenu.Page = (function(){

  return {
    filter : function(e,menu) {
        var offline = Offline.isOffline();
        ViewHelper.closeAllDialogs();
        if($(e.target).parents("'.zoomed_folio'").length == 0){
          $('#page_zoom_in',menu).show();
          $('#page_zoom_out',menu).hide();
        }else{
          $('#page_zoom_out',menu).show();
          $('#page_zoom_in',menu).hide();
        }

        if($("#button_link_share").length == 0 || offline){
            $("#page_share", menu).hide();
        }

        if($("#navbar_subscribe").length == 0|| offline){
           $("#page_buy", menu).hide();
        }

        if($("#button_link_clip").length == 0|| offline){
            $("#page_clip", menu).hide();
        }

        if(offline){
            $("#page_social_icons", menu).hide();
        }

        menu.html(ViewHelper.shadowWrap(menu));

        Share.collapsibleIcons.init(menu);

        if(Search.View.isDefaultValue == false){
            Search.View.updateSearchMeta();
        }
        $("#page_context_search_form",menu).unbind('submit').submit(function(event){
          event.preventDefault();
          event.stopPropagation();
          Search.View.submitBehavior($(this));
        });
        $("#search_submit_context",menu).unbind('click').bind('click',function(){
          var parent_form = $(this).parents("form.search_form",menu);
          Search.View.submitBehavior(parent_form);
        });
        $("#page_context_search_box",menu).unbind('focus').bind('focus',function(){
            if(Search.Model.getSearchValue() == "" || Search.View.isDefaultValue === true){
              $(this).val("");
            }
        }).unbind('blur').bind('blur',function(){
            val = $(this).val();
            if(Search.View.isDefaultValue===false && val != ""){
                Search.Model.setSearchValue(val);
            }else{
                var current_search_value = Search.Model.getSearchValue();
                if(current_search_value){
                    $(this).val(current_search_value);
                }else{
                    $(this).val("search");
                }
                Search.View.isDefaultValue = true;
            }
        }).unbind('keydown').bind('keydown',function(){
            if(Search.View.isDefaultValue===true){
                Search.View.isDefaultValue = false;
            }
        });
        return menu;
    },
    init : function() {
        $('div.page',PageModel.normalPagesDiv).contextMenu('page_context_menu', {
            bindings: {
              'page_zoom_in': function(t) {
                 PageController.handleZoomIn(t);
              },

              'page_zoom_out': function(t) {
                                PageController.handleZoomOut(t);
              },

              'page_share': function(t) {
                $("#button_link_share").trigger("click");
              },

              'page_clip': function(t) {
                $("#button_link_clip").trigger("click");
              },

              'page_buy': function() {
                document.location.href = $("#navbar_subscribe a").attr("href");
              },

              'page_help': function(t) {
                PageElements.tabs[0].tabs('select','help');
              }
            },
            menuStyle: {
                width:"200px",
                padding:"0"
            },
            itemStyle: {
                padding:"4px 0px 4px 0px",
                margin:"0"
            },
            shadow: false,
            onShowMenu: ViewHelper.ContextMenu.Page.filter
        });
    }
  }
})();

DomConfig = (function(){
    var active_configs = [];
    var configs = {
        "min": {
            "remove": [
                "#button_link_branding",
                "#navbar_subscribe",
                "#navbar_search",
                "#navbar_texterity",
                "#navbar_tools",
                "#drawer"
            ],
            "css_transform": [{
                    "exp": "#navbar",
                    "css": {
                        "width":"93%"
                    }
                }
            ]
        },
        "pages_buttons": {
            "remove": [
                "#navbar_wrapper",
                "#drawer"
            ]
        },
        "pages_buttons_fs": {
            "remove": [
                "#navbar_wrapper",
                "#drawer"
            ],
            "show": [
                "#fulscrdiv"
            ]
        },

        "pages": {
            "remove": [
                "#navbar_wrapper",
                "#drawer",
                "#prevPageMargin",
                "#nextPageMargin"
            ]
        },
        "basic": {
            "move": [{
                    "exp": "#navbar_pagination",
                    "insert_method": "after",
                    "insert_location": "#navbar_subscribe",
                    "css": {
                        "position": "",
                        "float": "left"
                    }
                }
            ],
            "remove": [
                "#navbar_search",
                "#navbar_texterity",
                "#navbar_tools"
            ],
            "css_transform": [{
                    "exp": "#navbar",
                    "css": {
                        "width":"93%"
                    }
                }
            ]
        },
        "unbranded": {
            "remove": [
                "#button_link_branding",
                "#navbar_texterity"
            ]
        }
    }

    function element_remove(exp,scope){
        var element = $(exp,scope);
        if(element.length){
            element.remove();
        }
    }

    function element_show(exp,scope){
        var element = $(exp,scope);
        if(element.length){
            element.show();
        }
    }

    function element_hide(exp,scope){
        var element = $(exp,scope);
        if(element.length){
            element.hide();
        }
    }

    function element_move(obj,scope){
        var insert_method = obj.hasOwnProperty("insert_method") ? obj.insert_method : "after";
        var element = $(obj.exp,scope);
        var insert_location = $(obj.insert_location,scope);
        var call_method = insert_location[insert_method];
        if(element.length){
            element.clone(true);
            if(obj.hasOwnProperty("css")){
                element.css(obj.css);
            }
            call_method.call(insert_location,element);
        }
    }

    function element_css_transform(obj,scope){
        if(obj.hasOwnProperty("exp") && obj.hasOwnProperty("css") && ViewHelper.trueTypeOf(obj.css)=="object"){
            var element = $(obj.exp,scope);
            if(element.length){
                element.addClass("modified").css(obj.css);
            }
        }
    }

    function evaluate(config_name,scope){
        var config = configs[config_name];
        if(config.hasOwnProperty("move")){
            for(var i=0;i<config.move.length;i++){
                var move_me = config.move[i];
                if(move_me.hasOwnProperty("exp") && move_me.hasOwnProperty("insert_location")){
                    element_move(move_me,scope);
                }
            }
        }
        if(config.hasOwnProperty("remove")){
            for(var i=0;i<config.remove.length;i++){
                element_remove(config.remove[i],scope);
            }
        }
        if(config.hasOwnProperty("show")){
            for(var i=0;i<config.show.length;i++){
                element_show(config.show[i],scope);
            }
        }
        if(config.hasOwnProperty("hide")){
            for(var i=0;i<config.hide.length;i++){
                element_hide(config.hide[i],scope);
            }
        }
        if(config.hasOwnProperty("css_transform")){
            for(var i=0;i<config.css_transform.length;i++){
                element_css_transform(config.css_transform[i],scope);
            }
        }
    }

    return {
        init: function(){
            if(location.search.indexOf("mode=")!=-1){
                this.activate(jQuery.url.param("mode"));
            }
            if(active_configs.length > 0){
                for(var i=0;i<active_configs.length;i++){
                    this.execute(active_configs[i]);
                }
            }
        },
        activate: function(config){
            if(typeof configs[config] != "undefined"){
                active_configs.push(config);
            }
        },
        execute: function(config_name,scope_arg){
            var scope = $(scope_arg) || $("body");
            evaluate(config_name,scope);
        },
        add: function(data){
            if(ViewHelper.trueTypeOf(data)=="object" && data.hasOwnProperty("name") && data.hasOwnProperty("config") && ViewHelper.trueTypeOf(data.config)=="object"){
                configs[data.name] = data.config;
            }
        }
    }
})();


jQuery.url=function(){var segments={};var parsed={};var options={url:window.location,strictMode:false,key:["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"],q:{name:"queryKey",parser:/(?:^|&)([^&=]*)=?([^&]*)/g},parser:{strict:/^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/,loose:/^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/}};var parseUri=function(){str=decodeURI(options.url);var m=options.parser[options.strictMode?"strict":"loose"].exec(str);var uri={};var i=14;while(i--){uri[options.key[i]]=m[i]||""}uri[options.q.name]={};uri[options.key[12]].replace(options.q.parser,function($0,$1,$2){if($1){uri[options.q.name][$1]=$2}});return uri};var key=function(key){if(!parsed.length){setUp()}if(key=="base"){if(parsed.port!==null&&parsed.port!==""){return parsed.protocol+"://"+parsed.host+":"+parsed.port+"/"}else{return parsed.protocol+"://"+parsed.host+"/"}}return(parsed[key]==="")?null:parsed[key]};var param=function(item){if(!parsed.length){setUp()}return(parsed.queryKey[item]===null)?null:parsed.queryKey[item]};var setUp=function(){parsed=parseUri();getSegments()};var getSegments=function(){var p=parsed.path;segments=[];segments=parsed.path.length==1?{}:(p.charAt(p.length-1)=="/"?p.substring(1,p.length-1):path=p.substring(1)).split("/")};return{setMode:function(mode){strictMode=mode=="strict"?true:false;return this},setUrl:function(newUri){options.url=newUri===undefined?window.location:newUri;setUp();return this},segment:function(pos){if(!parsed.length){setUp()}if(pos===undefined){return segments.length}return(segments[pos]===""||segments[pos]===undefined)?null:segments[pos]},attr:key,param:param}}();

/*! Copyright (c) 2009 Brandon Aaron (http://brandonaaron.net)
* Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
* and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
* Thanks to: http://adomas.org/javascript-mouse-wheel/ for some pointers.
* Thanks to: Mathias Bank(http://www.mathias-bank.de) for a scope bug fix.
*
* Version: 3.0.2
*
* Requires: 1.2.2+
*/

(function($) {

var types = ['DOMMouseScroll', 'mousewheel'];

$.event.special.mousewheel = {
  setup: function() {
    if ( this.addEventListener )
      for ( var i=types.length; i; )
        this.addEventListener( types[--i], handler, false );
    else
      this.onmousewheel = handler;
  },

  teardown: function() {
    if ( this.removeEventListener )
      for ( var i=types.length; i; )
        this.removeEventListener( types[--i], handler, false );
    else
      this.onmousewheel = null;
  }
};

$.fn.extend({
  mousewheel: function(fn) {
    return fn ? this.bind("mousewheel", fn) : this.trigger("mousewheel");
  },

  unmousewheel: function(fn) {
    return this.unbind("mousewheel", fn);
  }
});


function handler(event) {
  var args = [].slice.call( arguments, 1 ), delta = 0, returnValue = true;

  event = $.event.fix(event || window.event);
  event.type = "mousewheel";

  if ( event.wheelDelta ) delta = event.wheelDelta/120;
  if ( event.detail ) delta = -event.detail/3;

  // Add events and delta to the front of the arguments
  args.unshift(event, delta);

  return $.event.handle.apply(this, args);
}

})(jQuery);


/*
 * jQuery Event Delegation Plugin - jquery.eventdelegation.js
 * Fast flexible event handling
 *
 * January 2008 - Randy Morey (http://dev.distilldesign.com/)
 */

(function ($) {
  /* setup list of allowed events for event delegation
   * only events that bubble are appropriate
   */
  var allowed = {};
  $.each([
    'click',
    'dblclick',
    'mousedown',
    'mouseup',
    'mousemove',
    'mouseover',
    'mouseout',
    'keydown',
    'keypress',
    'keyup'
    ], function(i, eventName) {
      allowed[eventName] = true;
  });

  $.fn.extend({
    delegate: function (event, selector, f) {
      return $(this).each(function () {
        if (allowed[event])
          $(this).bind(event, function (e) {
            var el = $(e.target),
              result = false;

            while (!$(el).is('body')) {
              if ($(el).is(selector)) {
                result = f.apply($(el)[0], [e]);
                if (result === false)
                  e.preventDefault();
                return;
              }

              el = $(el).parent();
            }
          });
      });
    },
    undelegate: function (event) {
      return $(this).each(function () {
        $(this).unbind(event);
      });
    }
  });
})(jQuery);


/*
 * jQuery corner plugin
 *
 * version 1.92 (12/18/2007)
 *
 * Dual licensed under the MIT and GPL licenses:
 *   http://www.opensource.org/licenses/mit-license.php
 *   http://www.gnu.org/licenses/gpl.html
 */
/**
 *
 * @name corner
 * @type jQuery
 * @param String options Options which control the corner style
 * @cat Plugins/Corner
 * @return jQuery
 * @author Dave Methvin (dave.methvin@gmail.com)
 * @author Mike Alsup (malsup@gmail.com)
 */
(function($) {

$.fn.corner = function(o) {
    var ie6 = $.browser.msie && /MSIE 6.0/.test(navigator.userAgent);
    function sz(el, p) { return parseInt($.css(el,p))||0; };
    function hex2(s) {
        var s = parseInt(s).toString(16);
        return ( s.length < 2 ) ? '0'+s : s;
    };
    function gpc(node) {
        for ( ; node && node.nodeName.toLowerCase() != 'html'; node = node.parentNode ) {
            var v = $.css(node,'backgroundColor');
            if ( v.indexOf('rgb') >= 0 ) {
                if ($.browser.safari && v == 'rgba(0, 0, 0, 0)')
                    continue;
                var rgb = v.match(/\d+/g);
                return '#'+ hex2(rgb[0]) + hex2(rgb[1]) + hex2(rgb[2]);
            }
            if ( v && v != 'transparent' )
                return v;
        }
        return '#ffffff';
    };
    function getW(i) {
        switch(fx) {
        case 'round':  return Math.round(width*(1-Math.cos(Math.asin(i/width))));
        case 'cool':   return Math.round(width*(1+Math.cos(Math.asin(i/width))));
        case 'sharp':  return Math.round(width*(1-Math.cos(Math.acos(i/width))));
        case 'bite':   return Math.round(width*(Math.cos(Math.asin((width-i-1)/width))));
        case 'slide':  return Math.round(width*(Math.atan2(i,width/i)));
        case 'jut':    return Math.round(width*(Math.atan2(width,(width-i-1))));
        case 'curl':   return Math.round(width*(Math.atan(i)));
        case 'tear':   return Math.round(width*(Math.cos(i)));
        case 'wicked': return Math.round(width*(Math.tan(i)));
        case 'long':   return Math.round(width*(Math.sqrt(i)));
        case 'sculpt': return Math.round(width*(Math.log((width-i-1),width)));
        case 'dog':    return (i&1) ? (i+1) : width;
        case 'dog2':   return (i&2) ? (i+1) : width;
        case 'dog3':   return (i&3) ? (i+1) : width;
        case 'fray':   return (i%2)*width;
        case 'notch':  return width;
        case 'bevel':  return i+1;
        }
    };
    o = (o||"").toLowerCase();
    var keep = /keep/.test(o);                       // keep borders?
    var cc = ((o.match(/cc:(#[0-9a-f]+)/)||[])[1]);  // corner color
    var sc = ((o.match(/sc:(#[0-9a-f]+)/)||[])[1]);  // strip color
    var width = parseInt((o.match(/(\d+)px/)||[])[1]) || 10; // corner width
    var re = /round|bevel|notch|bite|cool|sharp|slide|jut|curl|tear|fray|wicked|sculpt|long|dog3|dog2|dog/;
    var fx = ((o.match(re)||['round'])[0]);
    var edges = { T:0, B:1 };
    var opts = {
        TL:  /top|tl/.test(o),       TR:  /top|tr/.test(o),
        BL:  /bottom|bl/.test(o),    BR:  /bottom|br/.test(o)
    };
    if ( !opts.TL && !opts.TR && !opts.BL && !opts.BR )
        opts = { TL:1, TR:1, BL:1, BR:1 };
    var strip = document.createElement('div');
    strip.style.overflow = 'hidden';
    strip.style.height = '1px';
    strip.style.backgroundColor = sc || 'transparent';
    strip.style.borderStyle = 'solid';
    return this.each(function(index){
        var pad = {
            T: parseInt($.css(this,'paddingTop'))||0,     R: parseInt($.css(this,'paddingRight'))||0,
            B: parseInt($.css(this,'paddingBottom'))||0,  L: parseInt($.css(this,'paddingLeft'))||0
        };

        if ($.browser.msie) this.style.zoom = 1; // force 'hasLayout' in IE
        if (!keep) this.style.border = 'none';
        strip.style.borderColor = cc || gpc(this.parentNode);
        var cssHeight = $.curCSS(this, 'height');

        for (var j in edges) {
            var bot = edges[j];
            // only add stips if needed
            if ((bot && (opts.BL || opts.BR)) || (!bot && (opts.TL || opts.TR))) {
                strip.style.borderStyle = 'none '+(opts[j+'R']?'solid':'none')+' none '+(opts[j+'L']?'solid':'none');
                var d = document.createElement('div');
                $(d).addClass('jquery-corner');
                var ds = d.style;

                bot ? this.appendChild(d) : this.insertBefore(d, this.firstChild);

                if (bot && cssHeight != 'auto') {
                    if ($.css(this,'position') == 'static')
                        this.style.position = 'relative';
                    ds.position = 'absolute';
                    ds.bottom = ds.left = ds.padding = ds.margin = '0';
                    ds.bottom = "-1";
                    if ($.browser.msie)
                        ds.setExpression('width', 'this.parentNode.offsetWidth');
                    else
                        ds.width = '100%';
                }
                else if (!bot && $.browser.msie) {
                    if ($.css(this,'position') == 'static')
                        this.style.position = 'relative';
                    ds.position = 'absolute';
                    ds.top = ds.left = ds.right = ds.padding = ds.margin = '0';

                    // fix ie6 problem when blocked element has a border width
                    var bw = 0;
                    if (ie6 || !$.boxModel)
                        bw = sz(this,'borderLeftWidth') + sz(this,'borderRightWidth');
                    ie6 ? ds.setExpression('width', 'this.parentNode.offsetWidth - '+bw+'+ "px"') : ds.width = '100%';
                }
                else {
                    ds.margin = !bot ? '-'+pad.T+'px -'+pad.R+'px '+(pad.T-width)+'px -'+pad.L+'px' :
                                        (pad.B-width)+'px -'+pad.R+'px -'+pad.B+'px -'+pad.L+'px';
                }

                for (var i=0; i < width; i++) {
                    var w = Math.max(0,getW(i));
                    var e = strip.cloneNode(false);
                    e.style.borderWidth = '0 '+(opts[j+'R']?w:0)+'px 0 '+(opts[j+'L']?w:0)+'px';
                    bot ? d.appendChild(e) : d.insertBefore(e, d.firstChild);
                }
            }
        }
    });
};

$.fn.uncorner = function(o) { return $('.jquery-corner', this).remove(); };

})(jQuery);


/*
 * ContextMenu - jQuery plugin for right-click context menus
 *
 * Author: Chris Domigan
 * Contributors: Dan G. Switzer, II
 * Parts of this plugin are inspired by Joern Zaefferer's Tooltip plugin
 *
 * Dual licensed under the MIT and GPL licenses:
 *   http://www.opensource.org/licenses/mit-license.php
 *   http://www.gnu.org/licenses/gpl.html
 *
 * Version: r2
 * Date: 16 July 2007
 *
 * For documentation visit http://www.trendskitchens.co.nz/jquery/contextmenu/
 *
 */

(function($) {

  var menu, shadow, trigger, content, hash, currentTarget;
  var defaults = {
    menuStyle: {
      listStyle: 'none',
      padding: '10px 1px',
      margin: '0px',
      backgroundColor: '#999',
      width: 'auto'
    },
    itemStyle: {
      margin: '0px',
      color: '#000',
      display: 'block',
      fontSize: '12px',
      padding: '3px',
      backgroundColor: 'transparent',
      textDecoration: 'none'
    },
    itemHoverStyle: {
        textDecoration: 'underline'
    },
    eventPosX: 'pageX',
    eventPosY: 'pageY',
    shadow : true,
    onContextMenu: null,
    onShowMenu: null
  };

  $.fn.contextMenu = function(id, options) {
    if (!menu) {                                      // Create singleton menu
      menu = $('<div id="jqContextMenu"></div>')
               .hide()
               .css({position:'absolute', zIndex:'500'})
               .appendTo('body')
               .bind('click', function(e) {
                 e.stopPropagation();
               });
    }
    if (!shadow) {
      shadow = $('<div></div>')
                 .css({backgroundColor:'#000',position:'absolute',opacity:0.2,zIndex:499})
                 .appendTo('body')
                 .hide();
    }
    hash = hash || [];
    hash.push({
      id : id,
      menuStyle: $.extend({}, defaults.menuStyle, options.menuStyle || {}),
      itemStyle: $.extend({}, defaults.itemStyle, options.itemStyle || {}),
      itemHoverStyle: $.extend({}, defaults.itemHoverStyle, options.itemHoverStyle || {}),
      bindings: options.bindings || {},
      shadow: options.shadow || options.shadow === false ? options.shadow : defaults.shadow,
      onContextMenu: options.onContextMenu || defaults.onContextMenu,
      onShowMenu: options.onShowMenu || defaults.onShowMenu,
      eventPosX: options.eventPosX || defaults.eventPosX,
      eventPosY: options.eventPosY || defaults.eventPosY
    });

    var index = hash.length - 1;
    $(this).unbind('contextmenu').bind('contextmenu', function(e) {
      // Check if onContextMenu() defined
      var bShowContext = (!!hash[index].onContextMenu) ? hash[index].onContextMenu(e) : true;
      if (bShowContext) display(index, this, e, options);
      return false;
    });
    return this;
  };

  function display(index, trigger, e, options) {
    var cur = hash[index];
    content = $('#'+cur.id).find('ul:first').clone(true);
    content.css(cur.menuStyle).find('li').css(cur.itemStyle).find('img').css({verticalAlign:'middle',paddingRight:'2px'});

    // Send the content to the menu
    menu.html(content);

    // if there's an onShowMenu, run it now -- must run after content has been added
    // if you try to alter the content variable before the menu.html(), IE6 has issues
    // updating the content
    if (!!cur.onShowMenu) menu = cur.onShowMenu(e, menu);

    $.each(cur.bindings, function(id, func) {
      $('#'+id, menu).bind('click', function(e) {
        hide();
        func(trigger, currentTarget);
      });
    });

        if((e[cur.eventPosX] - $(window).scrollLeft()) + parseInt(cur.menuStyle.width) > $(window).width()){
            var left_pos = e[cur.eventPosX] - (e[cur.eventPosX] + parseInt(cur.menuStyle.width) - $(window).width()) - 30 + $(window).scrollLeft();
        }else{
            var left_pos = e[cur.eventPosX];
        }

    menu.css({'left':left_pos,'top':e[cur.eventPosY]}).show();
    $("li",menu).hover(
      function() {
        $(this).css(cur.itemHoverStyle);
      },
      function(){
        $(this).css(cur.itemStyle);
      }
    );
    if (cur.shadow) shadow.css({width:menu.width(),height:menu.height(),left:e.pageX+2,top:e.pageY+2}).show();
    $("*").one('click', hide);
  }

  function hide(event) {
    if(event){
        var target = $(event.target);
        if (target.is('#jqContextMenu') || target.parents('#jqContextMenu').length) {
            return;
        }
    }
    menu.hide();
    shadow.hide();
  }

  // Apply defaults
  $.contextMenu = {
    defaults : function(userDefaults) {
      $.each(userDefaults, function(i, val) {
        if (typeof val == 'object' && defaults[i]) {
          $.extend(defaults[i], val);
        }
        else defaults[i] = val;
      });
    }
  };

})(jQuery);

$(function() {
  $('div.contextMenu').hide();
});


/**
 * History/Remote - jQuery plugin for enabling history support and bookmarking
 * @requires jQuery v1.0.3
 *
 * http://stilbuero.de/jquery/history/
 *
 * Copyright (c) 2006 Klaus Hartl (stilbuero.de)
 * Dual licensed under the MIT and GPL licenses:
 * http://www.opensource.org/licenses/mit-license.php
 * http://www.gnu.org/licenses/gpl.html
 *
 * Version: 0.2.3
 * Modified by Texterity, Inc. 2008
 */

(function($) { // block scope

/**
 * Initialize the history manager. Subsequent calls will not result in additional history state change
 * listeners. Should be called soonest when the DOM is ready, because in IE an iframe needs to be added
 * to the body to enable history support.
 *
 * @example $.ajaxHistory.initialize();
 *
 * @param Function callback A single function that will be executed in case there is no fragment
 *                          identifier in the URL, for example after navigating back to the initial
 *                          state. Use to restore such an initial application state.
 *                          Optional. If specified it will overwrite the default action of
 *                          emptying all containers that are used to load content into.
 * @type undefined
 *
 * @name $.ajaxHistory.initialize()
 * @cat Plugins/History
 * @author Klaus Hartl/klaus.hartl@stilbuero.de
 */
$.ajaxHistory = new function() {

    var RESET_EVENT = 'historyReset';
    var _actionFlag = 0;

    var _currentHash = document.location.hash;
    var _intervalId = null;
    var _observeHistory; // define outside if/else required by Opera

    this.update = function() { }; // empty function body for graceful degradation

    // create custom event for state reset
    var _defaultReset = function() {
        $('.remote-output').empty();
    };
    $(document).bind(RESET_EVENT, _defaultReset);

    // TODO fix for Safari 3
    // if ($.browser.msie)
    // else if hash != _currentHash
    // else check history length

    if ($.browser.msie) {

        var _historyIframe, initialized = false; // for IE

        // add hidden iframe
        $(function() {
            _historyIframe = $('<iframe style="display: none;"></iframe>').appendTo(document.body).get(0);
            var iframe = _historyIframe.contentWindow.document;
            // create initial history entry
            iframe.open();
            iframe.close();
            if (_currentHash && _currentHash != '#') {
                iframe.location.hash = _currentHash.replace('#', '');
            }
        });

        this.update = function(hash) {
            _currentHash = '#' + hash;
            var iframe = _historyIframe.contentWindow.document;
            iframe.open();
            iframe.close();
            if (iframe.location.hash != _currentHash) {
                iframe.location.hash = hash;
            }
            document.location.hash = hash;
        };

        _observeHistory = function() {
          if (!_actionFlag) {
            var iframe = _historyIframe.contentWindow.document;
            var iframeHash = iframe.location.hash;
            if (!iframeHash || iframeHash == '#') {
                return;
            }
            if (iframeHash != _currentHash) {
                _currentHash = iframeHash;
                if (iframeHash && iframeHash != '#') {
                    // order does matter, set location.hash after triggering the click...
                    var articleHash = "#"+ArticleViewer.hashParamName+"=";
                    if (_currentHash.indexOf(articleHash) != -1) {
                        var article_id = _currentHash.replace(articleHash,"").toString();
                        if (article_id != "" && ArticleViewer.Articles.data.hasOwnProperty(article_id)) {
                            ArticleViewer.viewArticle(article_id);
                        }
                    } else if (_currentHash.indexOf("#pg") != -1) {
                        var page = parseInt(_currentHash.replace("#pg",""),10);
                        if(!isNaN(page) && PageModel.pages.hasOwnProperty(page)){
                            PageController.handleGoToPage(page);
                        }
                    }
                } else if (initialized) {
                    document.location.hash = '';
                    $(document).trigger(RESET_EVENT);
                }
            }
            initialized = true;
          }
        };

    } else if ($.browser.mozilla || $.browser.opera) {

        this.update = function(hash) {
            _currentHash = '#' + hash;
            document.location.hash = hash;
        };

        _observeHistory = function() {
          if (!_actionFlag) {
            if (document.location.hash) {
                if (_currentHash != document.location.hash) {
                    _currentHash = document.location.hash;
                    var articleHash = "#"+ArticleViewer.hashParamName+"=";
                    if (_currentHash.indexOf(articleHash) != -1) {
                        var article_id = _currentHash.replace(articleHash,"").toString();
                        if (article_id != "" && ArticleViewer.Articles.data.hasOwnProperty(article_id)) {
                            ArticleViewer.viewArticle(article_id);
                        }
                    } else if (_currentHash.indexOf("#pg") != -1) {
                        var page = parseInt(_currentHash.replace("#pg",""),10);
                        if(!isNaN(page) && PageModel.pages.hasOwnProperty(page)){
                            PageController.handleGoToPage(page);
                        }
                    }
                }
            } else if (_currentHash) {
                _currentHash = '';
                $(document).trigger(RESET_EVENT);
            }
          }
        };

    } else if ($.browser.safari) {

        var _backStack, _forwardStack, _addHistory; // for Safari

        // etablish back/forward stacks
        $(function() {
            _backStack = [];
            _backStack.length = history.length;
            _forwardStack = [];
            jQuery.lastHistoryLength = history.length;

        });
        var isFirst = false, initialized = false;
        _addHistory = function(hash) {
            _backStack.push(hash);
            _forwardStack.length = 0; // clear forwardStack (true click occured)
            isFirst = false;
        };

        this.update = function(hash) {
            _currentHash = '#' + hash;
            _addHistory(_currentHash);
            document.location.hash = hash;
        };

        _observeHistory = function() {
          if (!_actionFlag) {
         // Chrome support - chrome only keeps 50 history entries
         // so we need to make sure we cap it off at 50 as well...
         if(jQuery.lastHistoryLength == history.length && _backStack.length > jQuery.lastHistoryLength) {
            _backStack.shift();
         }

            var historyDelta = history.length - _backStack.length;
            jQuery.lastHistoryLength = history.length;
            if (historyDelta) { // back or forward button has been pushed
                isFirst = false;
                if (historyDelta < 0) { // back button has been pushed
                    // move items to forward stack
                    for (var i = 0; i < Math.abs(historyDelta); i++) _forwardStack.unshift(_backStack.pop());
                } else { // forward button has been pushed
                    // move items to back stack
                    for (var i = 0; i < historyDelta; i++) _backStack.push(_forwardStack.shift());
                }
                var cachedHash = _backStack[_backStack.length - 1];
                // tty - only click once
                var articleHash = "#"+ArticleViewer.hashParamName+"=";
                if (_currentHash.indexOf(articleHash) != -1) {
                    var article_id = _currentHash.replace(articleHash,"").toString();
                    if (article_id != "" && ArticleViewer.Articles.data.hasOwnProperty(article_id)) {
                        ArticleViewer.viewArticle(article_id);
                    }
                } else if (_currentHash.indexOf("#pg") != -1) {
                    var page = parseInt(_currentHash.replace("#pg",""),10);
                    if(!isNaN(page) && PageModel.pages.hasOwnProperty(page)){
                        PageController.handleGoToPage(page);
                    }
                }
                _currentHash = document.location.hash;
            } else if (_backStack[_backStack.length - 1] == undefined && !isFirst) {
                // back button has been pushed to beginning and URL already pointed to hash (e.g. a bookmark)
                // document.URL doesn't change in Safari
                if (document.URL.indexOf('#') >= 0) {
                    var page = parseInt(document.URL.split('#')[1].replace("pg",""),10);
                    if(!isNaN(page) && PageModel.pages.hasOwnProperty(page)){
                        PageController.handleGoToPage(page);
                    }
                } else if (initialized) {
                    $(document).trigger(RESET_EVENT);
                }
                isFirst = true;
            }
            initialized = true;
          }
        };

    }

    this.initialize = function(callback) {
        // custom callback to reset app state (no hash in url)
        if (typeof callback == 'function') {
            $(document).unbind(RESET_EVENT, _defaultReset).bind(RESET_EVENT, callback);
        }
        // look for hash in current URL (not Safari)
        if (document.location.hash && typeof _addHistory == 'undefined') {
            $('a[href$="' + document.location.hash + '"]').trigger('click');
        }
        // start observer
        if (_observeHistory && _intervalId == null) {
            _intervalId = setInterval(_observeHistory, 400); // Safari needs at least 200 ms
        }
    };

};


$.fn.remote = function(output, settings, callback) {

    callback = callback || function() {};
    if (typeof settings == 'function') { // shift arguments
        callback = settings;
    }

    settings = $.extend({
        hashPrefix: 'remote-'
    }, settings || {});

    var target = $(output).size() && $(output) || $('<div></div>').appendTo('body');
    target.addClass('remote-output');

    return this.each(function(i) {
        var href = this.href, hash = '#' + (this.title && this.title.replace(/\s/g, '_') || settings.hashPrefix + (i + 1)),
            a = this;
        this.href = hash;
        $(this).click(function(e) {
            // lock target to prevent double loading in Firefox
            if (!target['locked']) {
                // add to history only if true click occured, not a triggered click
                if (e.clientX) {
                    $.ajaxHistory.update(hash);
                }
                target.load(href, function() {
                    target['locked'] = null;
                    callback.apply(a);
                });
            }
        });
    });

};

$.fn.history = function(callback) {
    return this.click(function(e) {
    _actionFlag=1;
        // add to history only if true click occured, not a triggered click
        if (e.clientX) {
            $.ajaxHistory.update(this.hash);
        }
        // tty - pass event object to callback
        typeof callback == 'function' && callback(e);
    _actionFlag=0;
    });
};

})(jQuery);

CookieManager = (function(){
  var domain = new String();

  return {
    check: function() {
        var enabled = true;
        CookieManager.set("cookieEnabledTest", "true", 0);
        if (CookieManager.get("cookieEnabledTest")) {
            enabled = true;
        } else {
            enabled = false;
        }
        CookieManager.remove("cookieEnabledTest");
        return enabled;
    },

    get: function( c_name ){
        if (document.cookie.length > 0){
            var nameEqual = c_name + "=";
            var cookiesArray = document.cookie.split(';');
            for (var i = 0, len = cookiesArray.length; i < len; i++) {
                var cookie = ViewHelper.ltrim(cookiesArray[i], " ");
                if (cookie.indexOf(nameEqual) == 0) {
                    return unescape(cookie.substring(nameEqual.length, cookie.length));
                }
            }
        }
        return false;
    },

    set: function( c_name, val, days ){
      days = days ? days : 3000;
      var exp = new Date();
      exp.setDate(exp.getDate() + days);
      var c = c_name+"="+escape(val)+"; expires="+exp.toGMTString()+"; path=/;";
      document.cookie=c;
    },

    setWithPath: function( c_name, val, days, path ){
      days = days ? days : 3000;
      var exp = new Date();
      exp.setDate(exp.getDate() + days);
      var c = c_name+"="+escape(val)+"; expires="+exp.toGMTString()+"; path="+path+";";
      document.cookie=c;
    },

    remove: function( c_name ){
      var exp = new Date();
      if(CookieManager.get(c_name)){
          exp.setDate(exp.getDate()-3000); // expires 10 years ago
          document.cookie=c_name+"=; expires="+exp.toGMTString()+"; path=/;";
      }
    },

    getDomain: function(){
        return domain != "" ? domain : this.setDomain();
    },

    setDomain: function(val){
      if(!val){
        domain = document.domain;
      } else {
        domain = val;
      }
      return domain;
    }
  }
})();

Validate = (function(){
  email_pattern = /^[^\s()<>@,;:\/]+@\w[\w\.-]+\.[a-z]{2,}$/i;
  return {
    email: function(val){
      return email_pattern.test(val);
    }
  }
})();

/* Template class is from Prototype library */
/* It has been modified to function independently */


var Template = function(template, pattern){
    this.template = template;
    this.pattern = pattern || this.Pattern;
};
Template.prototype = {
  Pattern: /(^|.|\r|\n)(#\{(.*?)\})/,
  gsub: function(source, pattern, replacement) {
      var result = '', match;
      while (source.length > 0) {
        if (match = source.match(pattern)) {
          result += source.slice(0, match.index);
          result += replacement(match);
          source  = source.slice(match.index + match[0].length);
        } else {
          result += source, source = '';
        }
      }
      return result;
  },
  evaluate: function(object) {
      return this.gsub(this.template,this.pattern,function(match) {
        if (object == null) return '';
        var before = match[1] || '';
        if (before == '\\') return match[2];
        var ctx = object, expr = match[3];
        var pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/;
        match = pattern.exec(expr);
        if (match == null) return before;
        while (match != null) {
          var comp = match[1].indexOf('[') === 0 ? match[2].gsub('\\\\]', ']') : match[1];
          ctx = ctx[comp];
          if (null == ctx || '' == match[3]) break;
          expr = expr.substring('[' == match[3] ? match[1].length : match[0].length);
          match = pattern.exec(expr);
        }
        return before + ctx;
      });
  }
};

var Scroller = (function(element_id,opt) {

    // START PRIVATE STATIC ATTRIBUTES
    var scroller_template = String("<div class='ui-slider-#{orientation}-wrapper' style='width:#{wrapper_width};height:#{wrapper_height};'><div id='#{id}_slider_top' class='ui-slider-#{orientation}-top'></div><div id='#{id}-innerwrapper' class='ui-slider-#{orientation}-innerwrapper' style='height:#{height};width:#{width};top:#{wrapper_top};'><div id='#{id}' style='height:#{scroller_height};top:#{scroller_top};'></div></div><div id='#{id}_slider_bottom' class='ui-slider-#{orientation}-bottom'></div></div>");

    return function(element_id,opt){

      // START PRIVATE ATTRIBUTES
      var element; //cached jQuery object
      var that = this; //reference to current object
      var arrow_height = 12;
      var data = {};
      var options = typeof opt != "undefined" ? opt : {};

      // START PRIVILEGED METHODS

      //removes the scroller elements
      this.remove = function(){
          $(data.wrapper_id).replaceWith($("div:first",$(data.wrapper_id)).html());
          $("div[class*='ui-slider']",element).remove();
          element.removeClass("has_scroller").css({"overflow":"hidden","height":"","position":""});
      };

      //removes the scroller elements and deletes it from the list of known scrollers
      this.destroy = function(){
          this.remove();
          delete Scroller.scrollers[element_id];
      }

      this.reset = function(){
        if(data.has_scroller == false){
            that.setElementData();
            that.determineScrollingRequirements();
            that.create();
        }else{
            that.setElementData();
            var wrapper = $(data.wrapper_id,element);
            if(wrapper.length){
                try{
                  wrapper.width(data.width);
                  wrapper.height(data.height);
                  $("div.ui-slider-vertical-wrapper",element).height(data.height);
                  $("div.ui-slider-vertical-innerwrapper",element).height(data.height - (arrow_height * 2));
                  $("div.ui-slider-vertical",element).height(data.height - (arrow_height * 2)-40);
                  data.scroll_height = wrapper.get(0).scrollHeight;
                  var remove_vertical = (data.scroll_height - data.height) <= 0;
                  if(remove_vertical){
                      that.remove();
                  }
                }catch(e){}
            }
        }
      };

      this.setElement = function(){
        element = $("#" + element_id);
        var scrollable_child = $("div.scroll_content_override",element);
        if(scrollable_child.length > 0){
            element = scrollable_child
        }
        this.setElementData();
      };

      this.setElementData = function(){
        var tmp_height = element.innerHeight();
        var tmp_max_height = options.hasOwnProperty("height")
            ? options.height
            : (element.offsetParent().innerHeight() - element.get(0).offsetTop);
        var tmp_scroll_height = element.get(0).scrollHeight;
        var tmp_parent_height = element.parent().innerHeight();
        var tmp_scroll_increment = ((tmp_height/2)/tmp_parent_height)*100;

        data = {
            has_scroller: element.hasClass("has_scroller"),
            height: tmp_height,
            offset: element.offset(),
            max_height: tmp_max_height,
            needs_y: false,
            parent_height: tmp_parent_height,
            scroll_height: tmp_scroll_height,
            scroll_increment: tmp_scroll_increment,
            width: that.width(element),
            wrapper_id: "#wrapper_" + element_id,
            constrained_height: tmp_max_height - (12 * 2)
        };
      };

      this.prepareElement = function(orientation){
        var scroller_id = "scroller_" + orientation + "_" + element_id;
        var scroller_top = 0;
        var template_height = 0;
        var template_width = 0;
        var wrapper_width = 0;
        var wrapper_height = 0;

        if(orientation == "vertical"){
          wrapper_width = arrow_height + 2;
          wrapper_height = data.max_height;
          template_height = data.constrained_height;
          template_width = arrow_height;
          scroller_top = 20;
          if(data.has_scroller===false){
            element.wrapInner("<div id='wrapper_" + element_id + "' class='ui-slider-scroll-area' style='position:relative;height:"+data.max_height+"px;width:"+data.width+"px;overflow:hidden;'><div class='ui-slider-scroll-area-inner'></div></div>");
          }
        }

        element.css({"position":"relative","overflow":""}).addClass("has_scroller");

        // initialize, populate and append the scroller control template to the target
        var scroller_html = new Template(scroller_template);
        element.append(scroller_html.evaluate({
          'id':scroller_id,
          'orientation':orientation,
          'height':template_height + "px",
          'scroller_height':(template_height-40) + "px",
          'width':template_width + "px",
          'wrapper_top':arrow_height+"px",
          'scroller_top':scroller_top + "px",
          'wrapper_width':wrapper_width + "px",
          'wrapper_height':wrapper_height + "px"
        }));
      };

      this.determineScrollingRequirements = function() {
        if(options.height && options.height < data.height){
          data.needs_y = true;
        }else if(data.height > data.max_height && element.css("position")!="absolute"){
          data.needs_y = true;
        }
      };

      this.createVerticalScroller = function(){
        var mouseup = false;
        var scroller_id = "#scroller_vertical_" + element_id;
        $(data.wrapper_id).attr("scrollTop",0);
        $(scroller_id).slider({
          max: 1000,
          value: 1000,
          orientation: "vertical",
          animate: false,
          change: function(e,ui){
            var height = that.height(element);
            var maxScroll = ($(data.wrapper_id,element).get(0).scrollHeight - height);
            $(data.wrapper_id,element).attr("scrollTop", ((1000-ui.value) * maxScroll) / 1000);
          },
          slide: function(e,ui){
            var height = that.height(element);
            var maxScroll = ($(data.wrapper_id,element).get(0).scrollHeight - height);
            $(data.wrapper_id,element).attr("scrollTop",((1000-ui.value) * maxScroll) / 1000);
          }
        });

        $(scroller_id + "_slider_top").mousedown(function(){
          mouseup = false;
          var scroll_increment = data.scroll_increment;
          var slider_top_interval = setInterval(function(){
                if(mouseup == false){
                  $(scroller_id).slider("value", $(scroller_id).slider("value")+scroll_increment);
                }else{
                  clearInterval(slider_top_interval);
                }
              }, 20);
        }).mouseup(function(){mouseup = true});

        $(scroller_id + "_slider_bottom").mousedown(function(){
          mouseup = false;
          var scroll_increment = data.scroll_increment;
          var slider_bottom_interval = setInterval(function(){
                if(mouseup == false){
                  $(scroller_id).slider("value", $(scroller_id).slider("value")-scroll_increment);
                }else{
                  clearInterval(slider_bottom_interval);
                }
              }, 20);
        }).mouseup(function(){mouseup = true});

        $(element).bind('mousewheel', function(event, delta) {
            vel = Math.abs(delta)*20;
            if(delta > 0){
                $(scroller_id).slider("value", $(scroller_id).slider("value")+vel);
            }else{
                $(scroller_id).slider("value", $(scroller_id).slider("value")-vel);
            }
            return false;
        });


      };

      this.create = function() {
        if(data.needs_y){
            this.prepareElement("vertical");
            this.createVerticalScroller();
            Scroller.scrollers[element_id]=this;
        }
     }
      // CONSTRUCTOR CODE
        if(typeof Scroller.scrollers[element_id]=="undefined"){
          this.setElement();

          this.determineScrollingRequirements();
          this.create();
        }else{
          Scroller.scrollers[element_id].reset();
        }
    }
})();

Scroller.scrollers = new Object();

Scroller.getScrollerIds = function(){
    var current_scrollers = Scroller.scrollers;
    return $.map(current_scrollers,function(n,i){
       return n;
    });
}

Scroller.destroyAll = function(){
    var scroller_length = Scroller.scrollers.length;
    for (var i in Scroller.scrollers){
      Scroller.scrollers[i].destroy();
    }
}

Scroller.prototype = {
  height: function(element){
    return element.height() || parseInt(element.css('height'));
  },

  width: function(element){
    return element.width() || parseInt(element.css('width'));
  }
}

PageElements = (function(){
  return {
    dialogs: new Object(),
    popups: new Object(),
    tabs: new Array()
  }
})();

DocumentProperties = (function(){
  var documentUrl = null;
  var collectionDomain = null;
  var staticDomain = '';
  var title = null;
  var publishDate = null;
  var collectionTitle = null;
  var collectionUrl = null;
  var desktopShortcutIcon = null;
  var languageText = null;
  var modified = null;
  var lookInsidePages = "";
  var subIdCookieHack = false;
  return {
    getDocumentUrl: function(){
      if (documentUrl != null)
        return documentUrl;
        var url = window.location.pathname;
        if (url.indexOf('#') >= 0) url = url.substring(0,url.indexOf('#'));
        if (url.indexOf('?') >= 0) url = url.substring(0,url.indexOf('?'));
        if (url.lastIndexOf('/') == url.length - 1) url = url.substring(0,url.lastIndexOf('/'));
        documentUrl = url;
        return documentUrl;
    },
    getCollectionDomain: function(){
        if (collectionDomain != null)
          return collectionDomain;
          var url = window.location.href;
          if (url.indexOf('://') >= 0) url = url.substring(url.indexOf('://')+3);
          if (url.indexOf('/') >= 0) url = url.substring(0,url.indexOf('/'));
          collectionDomain = url;
          return collectionDomain;
      },
    setStaticDomain: function(value){
        if(value){
            staticDomain = value;
        }
    },
    getStaticDomain: function(){
        return staticDomain;
    },
    setTitle: function(value) {
      if(value)
         title = value;
    },
    getTitle:function() {
      return title;
    },
    setPublishDate: function(value){
      if(value)
         publishDate = value;
    },
    getPublishDate: function () {
      return publishDate;
    },
    getCollectionTitle: function () {
      return collectionTitle;
    },
    setCollectionTitle: function(value){
      collectionTitle=value;
    },
    getCollectionUrl: function () {
      return collectionUrl;
    },
    setCollectionUrl: function(value){
      collectionUrl=value;
    },
    getDesktopShortcutIcon: function () {
      return desktopShortcutIcon;
    },
    setDesktopShortcutIcon: function(value){
      desktopShortcutIcon=value;
    },
    getLanguageText: function () {
        return languageText;
    },
    setLanguageText: function (value){
        languageText = value;
    },
    setSubIdCookieHack: function(flag) {
        subIdCookieHack = flag;
    },
    getSubIdCookieHack: function() {
        return subIdCookieHack;
    }

  }
})();

/**
 * Provide our own debugging to write to:
 * a) the Javascript console if it exists - enabled by a
 *    browser's Javascript debugger.
 * b) our own div on the page if it exists - when this is turned
 *    on by including "TexterityDebugConsole=true" in the url.
 * If neither case is true, the message is thrown away.
 */
Console = (function(){
    return {
        log: function(message){
            if(window.console) {
                console.log(message);
            }
            if ($("#texterityDebugConsole").size() > 0) {
                $("#texterityDebugConsole").css("display", "block");
                $("#texterityDebugConsole").append("<div>LOG: "+message+"</div>");
            }
        },

        warn: function(message){
            if(window.console) {
                console.warn(message);
            }
            if ($("#texterityDebugConsole").size() > 0) {
                $("#texterityDebugConsole").css("display", "block");
                $("#texterityDebugConsole").append("<div>WARN: "+message+"</div>");
            }
        },

        error: function(message){
            if(window.console) {
                console.error(message);
            }
            if ($("#texterityDebugConsole").size() > 0) {
                $("#texterityDebugConsole").css("display", "block");
                $("#texterityDebugConsole").append("<div>ERROR: "+message+"</div>");
            }
        },

        debug: function(message){
            if(window.console) {
                console.debug(message);
            }
            if ($("#texterityDebugConsole").size() > 0) {
                $("#texterityDebugConsole").css("display", "block");
                $("#texterityDebugConsole").append("<div>DEBUG: "+message+"</div>");
            }
        },

        trace: function(message){
            if(window.console) {
                console.trace(message);
            }
            if ($("#texterityDebugConsole").size() > 0) {
                $("#texterityDebugConsole").css("display", "block");
                $("#texterityDebugConsole").append("<div>TRACE: "+message+"</div>");
            }
        }
    }
})();

function clip( whichpage, portal_domain ) {
    var document_url = DocumentProperties.getDocumentUrl();
    var sub_id = CookieManager.get('subscriber_id');
    var clip_url =
        'http://' + portal_domain + '/memberLibrary?cmd=add_clipping'
      + "&document_url=" + document_url
      + "&label="
      + "&page=" + whichpage
      + "&sub_id=" + sub_id
      + "&webreader=1"
      + "&referer=" + escape(window.location.href);
    $(ViewHelper.shadowWrap($("#clipframe").clone(),"black")).dialog({
        height:335,
        width:300,
        dialogClass: "black",
        overlay: {
            opacity: 0.2,
            background: "black"
        },
        resizable:false,
        draggable:false,
        close: function(){
            var that = $(this);
            that.css('display','none');
            $("iframe",that).attr('src','');
            setTimeout(function(){
                delete PageElements.dialogs[that.attr("creator")];
                that.dialog('destroy').remove();
                ViewHelper.setupKeyFunctions();
                PageView.enableButtons();
            },200);
        },
        open: function(){
                $("#button_link_clip_dialog").dialog("close");
                $("iframe",$(this)).attr('src',clip_url);
        }
    });
    setTimeout(function(){
        Tracker.trackPage({"category":"clip","page":whichpage,"pageName":document.location.protocol + "//" + document.location.host + document_url + "?t=clip_completed&pg=" + whichpage,"title":"Clip "+whichpage,"lochref":document.location.href});
    },0);
}

Clip = (function() {
    function handle_clippings_success(html) {
      Scroller.destroyAll();
        $("#clippings").html(html);
      PageElements.tabs[0].tabs('select','clippings');
        setTimeout(function(){
            ViewHelper.makeScrollable();
            Drawer.View.load_clippings();
        },700);
    }

   function handle_clip_success() {
      ViewHelper.closeAllDialogs();
      var doc_url = DocumentProperties.getDocumentUrl();
      DataSwitch.get({
            url: doc_url + "/Clippings.action",
            success: handle_clippings_success
        });
   }

   return  {
      openDrawer: function() {
         PageElements.tabs[0].tabs('select','clippings');
      },
      clipPage: function(page) {
         var doc_url = DocumentProperties.getDocumentUrl();
         var notes = $("#clipnotes").get(0).value;
         if (notes == "ADD YOUR NOTES") notes = "";
         DataSwitch.get({
            url:  doc_url + "/Clip_submit.action?pg=" + page + "&notes=" + escape(notes),
            success: handle_clip_success
         });
      },
      deleteClipping: function(clippingId) {
         var doc_url = DocumentProperties.getDocumentUrl();
         DataSwitch.get({
            url:  doc_url + "/Clip_delete.action?clippingId=" + clippingId,
            success: handle_clip_success
         });
      }
   }
})();

Share = (function(){
    var message_duration = 5000;
    var share = new Object();
    var friend_template = new Template('<div style="display:#{display};"><input type="checkbox" name="toEmailAddresses[]" id="#{email}" value="#{email}" /><label for="#{email}">#{email}</label></div>');
    var icon_template = new Template('<span class="social_span"><a href="#{url_template}" class="social_link #{class_name}" title="#{name}" target="_blank"></a></span>');
    var my_networks_cookie = 'my_networks';
    var my_networks = null;
    var social_networks = [{
            "name":"Facebook",
            "url_template":"http://www.facebook.com/sharer.php?u=#{shareUrl}&t=#{article}",
            "class_name":"share_facebook"
        },{
            "name":"Twitter",
            "url_template":"http://twitter.com/home/?status=#{shareUrl}",
            "class_name":"share_twitter"
        },{
            "name":"Linkedin",
            "url_template":"http://www.linkedin.com/shareArticle?mini=true&url=#{shareUrl}&title=#{article}",
            "class_name":"share_linkedin"
        },{
            "name":"Digg",
            "url_template":"http://digg.com/submit?phase=2&url=#{shareUrl}&title=#{article}",
            "class_name":"share_digg"
        },{
            "name":"BlinkList",
            "url_template":"http://www.blinklist.com/index.php?Action=Blink/addblink.php&Description=&Url=#{shareUrl}&Title=#{article}",
            "class_name":"share_blinklist"
        },{
            "name":"BlogMarks",
            "url_template":"http://blogmarks.net/my/new.php?mini=1&url=#{shareUrl}&title=#{article}",
            "class_name":"share_blogmarks"
        },{
            "name":"del.icio.us",
            "url_template":"http://del.icio.us/post?v=4&partner=texterity&noui&jump=close&url=#{shareUrl}&title=#{article}",
            "class_name":"share_delicious"
        },{
            "name":"Furl/Diigo",
            "url_template":"http://secure.diigo.com/post?url=#{shareUrl}&title=#{article}",
            "class_name":"share_furl"
        },{
            "name":"Newsvine",
            "url_template":"http://www.newsvine.com/_tools/seed&save?u=#{shareUrl}&h=#{article}",
            "class_name":"share_newsvine"
        },{
            "name":"Reddit",
            "url_template":"http://reddit.com/submit?url=#{shareUrl}&title=#{article}",
            "class_name":"share_reddit"
        },{
            "name":"stumbleupon",
            "url_template":"http://www.stumbleupon.com/submit?url=#{shareUrl}&title=#{article}",
            "class_name":"share_stumbleupon"
        },{
            "name":"Technorati",
            "url_template":"http://www.technorati.com/faves?add=#{shareUrl}",
            "class_name":"share_technorati"
        }]


    function update_widget_code(){
        var code_html = ViewHelper.trim($("#widget_code_wrapper",share).html());
        if(typeof ArticleViewer != "undefined" &&
                ArticleViewer.active === true &&
                ArticleViewer.article &&
                $("#widget_code",share).length > 0){
            var code_href = $("#widget_code_wrapper a",share)[0].href;
            var regex_href = new RegExp(code_href.replace("\?","\\?"),"g");
            var code_href_article = code_href + "&article_id="+ArticleViewer.article.article_id;
            code_html = code_html.replace(regex_href,code_href_article);
        }
        $("#widget_code",share).val(code_html);
    }

    /**
     * Get friend's email address out of the "friends" cookie and populate the
     * friend's email list in the Share dropdown.  The size of the friends_list
     * div is allowed to grow naturally until the number of friends exceeds
     * 10 addresses, then the list is fixed in size.
     * Note: The friends list is originally built in a Freemarker template:
     * inputEmail.ftl, which can pre-populate the email list from email addresses
     * stored in the server.  CURRENTLY DISABLED in inputEmail.ftl
     */
    function populate_friends(){
        var friend_checkboxes = "";
        var friends = [];
        var friends_list = CookieManager.get("friends");
        if(friends_list){
            friends = friends_list.split(",");
            for (var i=0;i<friends.length;i++){
                  friend_checkboxes += friend_template.evaluate({email: friends[i],display:"block"});
            }
        }
        $("#friends_list",share).append(friend_checkboxes);
        if($("#friends_list input",share).length > 10){
            $("#friends_list",share).css({"height":"220px","overflow":"auto"});
        }
        $("#friends_list",share).slideDown();
        if(friends_list || $("input[name^='toEmailAddresses']",share).length){
            $("#remove_selected_button, #remove_selected_span",share).css("display","inline-block");
        }
    }
    /**
     * Take 1 or more email addresses from the "new_friend" ("to" addresses in the GUI)
     * field and add them to the friends_list and the friends cookie.  A check is made
     * to ensure that no duplicate email addresses are entered.  As with populate_friends,
     * the list is allowed to grow until it exceeds 10 friends.
     * Note: There is no check to determine if the browser cookie can handle the amount of data
     * entered through the "new_friend" field.  If the data exceeds the browser cookie size,
     * it cannot be stored.  This does not affect other functionality in the form, except
     * that data will not be permanent and will be lost once the user closes the Share pulldown.
     *
     * @param value the value from the "new_friend" input field
     */
    function add_friend(value){
      var errors = [];
      var values = value.split(",");
      var friends_list = CookieManager.get('friends');
      var friends = friends_list ? friends_list.split(",") : [];
      var friends_dom = $("#friends",share);
      for (var i=0;i<values.length;i++){
          if(Validate.email(values[i])){
              if(jQuery.inArray(values[i],friends)==-1){
                  friends.push(values[i]);
                  $("#friends_list",friends_dom).append(friend_template.evaluate({email: values[i],display:"none"})).find("div:hidden").slideDown();
              }else{
                  var duplicate_friend_msg = $("#toEmailAddressesDuplicate").text() || "The email address you entered is already in your friends list";
                  $("#failure").remove();
                  $("#add_friend").after("<div id='failure' style='display:none;'>"+duplicate_friend_msg+"</div>");
                  $("#failure").slideDown("slow");
                  setTimeout(function(){$("#failure").slideUp("slow",function(){$(this).remove();})},message_duration);
              }
              $("input[value='"+ values[i] +"']",friends_dom).attr("checked","checked");
          }else{
              errors.push($("#toEmailAddressesInvalid").text() || "The email address you have provided is invalid");
          }
        }
        if(friends.length > 10){
            $("#friends_list",friends_dom).css({"height":"220px","overflow":"auto"});
        }

        if(errors.length > 0){
              $("#failure").remove();
              $("#add_friend").after("<div id='failure' style='display:none;'>"+errors.join("<br />")+"</div>");
              $("#failure").slideDown("slow");
              setTimeout(function(){$("#failure").slideUp("slow",function(){$(this).remove();})},message_duration);
        }else{
            CookieManager.set('friends',ViewHelper.trim(friends.join(","),","));
            $("#new_friend",share).val("");
            $("#remove_selected_button, #remove_selected_span",share).css("display","inline-block");
        }
    }

    /**
     * Return the checked email addresses from the form.
     *
     * @return a list of email addresses
     */
    function get_friends(){
        var friends = [];
        $("input[name^='toEmailAddresses']:checked",share).each(function(){
            friends.push($(this).val());
        });
        return friends;
    }

    /**
     * Remove email addresses that have been checked from the cookie and the UI.
     * Reset the size of the panel if the number of friends is <= 10.
     */
    function remove_friend(){
        var friends = CookieManager.get('friends');
        var friends_dom = $("#friends",share);
        var checked_friends = $("input[name^='toEmailAddresses']:checked",share);
        if(checked_friends.length){
            checked_friends.each(function(){
                var friend_to_remove = new RegExp($(this).attr("value") + ",?");
                friends = friends.replace(friend_to_remove,"");
                $(this).parent().slideUp("slow",function(){$(this).remove()});
            });
            if(friends!=""){
                CookieManager.set('friends',ViewHelper.trim(friends,","));
            }else{
                CookieManager.remove('friends');
            }
            var friends_list = friends ? friends.split(",") : [];
            if(friends_list.length <= 10){
                $("#friends_list",friends_dom).css({"height":"","overflow":""});
            }
        }else{
            var no_friends_selected_msg = $("#noFriendsSelectedMsg").text() || "Select at least one email address to remove";
            $("#failure").remove();
            $("#remove_selected_span").after("<div id='failure' style='display:none;'>"+no_friends_selected_msg+"</div>");
            $("#failure").slideDown("slow");
            setTimeout(function(){$("#failure").slideUp("slow",function(){$(this).remove();})},message_duration);
        }
        return false;
    }

    function prepare_add_friend_form(){
        $("#add_friend").unbind('click').bind('click',function(){$("form[name='add_friend_form']",share).trigger("submit")});
        $("form[name='add_friend_form']",share).submit(function(){
            add_friend($('#new_friend').val());
            return false;
        });
        $("#remove_selected_button, #remove_selected_span",share).click(remove_friend);
    }

    function handle_email_success(html){
        html = "<div id='success' style='display:none;'>" + html + "</div>";
        $("#share_email").append(html);
        $("#success").slideDown("slow");
        setTimeout(function(){$("#success").slideUp("slow",function(){$(this).remove()});},message_duration);
    }

    function handle_email_error(XMLHttpRequest, textStatus, errorThrow){
        $("#failure").remove();
        $("#share_email").append("<div id='failure' style='display:none;'><p>There was a problem with your request. Please try again.</p></div>");
        $("#failure").slideDown("slow");
        setTimeout(function(){$("#failure").slideUp("slow").remove();},message_duration);
    }

    function prepare_send_email_button(){
        $("#send_email",share).click(function(){
            var errors = [];
            if(Validate.email($("#fromEmailAddress").val())==false){
                var invalid_from_email = $("#fromEmailAddressInvalid").text() || "Please provide your email address in the from: field";
                errors.push(invalid_from_email);
            }
            if($("#subject").val()==""){
                var invalid_subject = $("#subjectInvalid").text() || "Please provide a subject for this email";
                errors.push(invalid_subject);
            }
            var doc_url = DocumentProperties.getDocumentUrl();
            var pm = PageModel.pageMode;
            var pgs = [];
            var friends = get_friends();
            if(friends.length == 0){
                var new_friend = $("#new_friend").val();
                if(Validate.email(new_friend)==false){
                    var no_friends = $("#toEmailAddressesEmpty").text() || "You need to specify at least one email recipient";
                    errors.push(no_friends);
                }else{
                    add_friend(new_friend);
                    friends.push(new_friend);
                }
            }

            if(errors.length){
                $("#failure").remove();
                $("#share_email").append("<div id='failure' style='display:none;'>"+errors.join("<br />")+"</div>");
                $("#failure").slideDown("slow");
                setTimeout(function(){$("#failure").slideUp("slow",function(){$(this).remove();})},message_duration);
                return;
            }

            $("#normalpages div.page").each(function(){
                pgs.push($(this).attr("pg"));
            });

            var request_data = [];
            for(var x=0;x<friends.length;x++){
                request_data.push('toEmailAddresses='+friends[x]);
            }
            var ccToSelf = $("#ccToSelf:checked").length ? "true" : "false";
            request_data.push('fromEmailAddress='+$("#fromEmailAddress").val());
            request_data.push('subject='+encodeURIComponent($("#subject").val()));
            request_data.push('message='+encodeURIComponent($("#message").val()));
            request_data.push('pg=' + PageController.currentPage);
            request_data.push('pm=' + pm);
            request_data.push('pgs=' + pgs[0] + ',' + pgs[pgs.length - 1]);
            request_data.push('ccToSelf='+ccToSelf);
            request_data.push('u1=' + PageModel.u1);
            if(typeof ArticleViewer != "undefined" && ArticleViewer.active === true && ArticleViewer.article){
                request_data.push('article_id='+ArticleViewer.article.article_id);
            }
            DataSwitch.post({
                url: doc_url + "/Share_share.action",
                data: request_data.join("&"),
                success: handle_email_success,
                error: handle_email_error
            });
            // DT-4913 Do *not* track Share action request_data - privacy concern
            setTimeout(function(){
                Tracker.trackPage({"category":"share","share_type":"email","email_numbers":friends.length,"pageName":document.location.protocol + "//" + document.location.host + doc_url + "?t=Share_share&pgs="+pgs[0]+","+pgs[pgs.length - 1],"title":"Share "+pgs[0]+","+pgs[pgs.length - 1],"lochref":document.location.href});
            },0);
        });
    }

    function set_share(){
        share = $("#button_link_share_content");
    }

    return {

        init: function(){
            set_share();
            $("#share_widget_header",share).click(function(){
                setTimeout(function(){$("#widget_code").focus()},500);
            });
            $("#share_link_header",share).click(function(){
                setTimeout(function(){$("#direct_link").focus()},500);
            });
            if(typeof ArticleViewer != "undefined" && ArticleViewer.active === true && ArticleViewer.article){
                var direct_link = $("#direct_link",share);
                var direct_link_href = direct_link.val();
                direct_link.val(direct_link_href += "&article_id="+ArticleViewer.article.article_id);
            }
            $("#direct_link,#widget_code",share).bind('focus',function(){
                var that = $(this);
                //for safari, we have to remove readonly, select and then re-add readonly
                that.removeAttr('readonly').select().attr('readonly',true);
                var doc_url = DocumentProperties.getDocumentUrl();
                setTimeout(function(){
                    Tracker.trackPage({"category":"share","share_type":"panel_"+that.attr("id"),"pageName":document.location.protocol + "//" + document.location.host + doc_url + "?t=Share_" + that.attr("id"),"title":"Share panel "+that.attr("id"),"lochref":document.location.href});
                },0);
            });
            $("#new_friend,#fromEmailAddress",share).focus(function(){
                if($(this).val().indexOf("@")==-1){
                    $(this).val("");
                }
            });
            $("#from",share).blur(function(){
                if($(this).val()==""){
                    $(this).val("type your email address here");
                }
            });
            $("input[name='top_right_text']",share).blur(function(){$("#top_right_text").text($(this).val());update_widget_code();});
            $("input[name='bottom_text']",share).blur(function(){$("#bottom_text").text($(this).val());update_widget_code();});
            $("input[name='top_right_text']",share).keydown(function(e){ if (e.keyCode == 13) { $("#top_right_text").text($(this).val());update_widget_code();} });
            $("input[name='bottom_text']",share).keydown(function(e){ if (e.keyCode == 13) { $("#bottom_text").text($(this).val());update_widget_code();} });

            $("#direct_link_button",share).click(function(){
                $("#direct_link",share).focus();
                var doc_url = DocumentProperties.getDocumentUrl();
                setTimeout(function(){
                    Tracker.trackPage({"category":"share","share_type":"widget","pageName":document.location.protocol + "//" + document.location.host + doc_url + "?t=Share_widget","title":"Share widget","lochref":document.location.href});
                },100);
            });
            Share.initSocialNetworkIcons(share);
            update_widget_code();
            prepare_add_friend_form();
            prepare_send_email_button();
            populate_friends();
            CookieManager.setDomain()
        },

        initSocialNetworkIcons: function(scope){
            var element = $(".social_icons",scope);
            var share_url = 'http://' + DocumentProperties.getCollectionDomain()
                  + DocumentProperties.getDocumentUrl()
                  + escape("?pg=" + PageController.currentPage
                  +"&pm=" + PageModel.pageMode
                  + "&u1=" + PageModel.u1
                  + "&linkImageSrc=" + $(".folio").attr('thumbnail') + "/");
            Share.setCustomSocialNetworksOrder();
            Share.setSocialNetworkElementHtml(element,share_url);
        },

        getSocialNetworks: function(){
            return social_networks;
        },

        setSocialNetworks: function(values){
            if(ViewHelper.trueTypeOf(values)=="array"){
                social_networks = values;
            }
        },

        setCustomSocialNetworksOrder: function(){
            var my_nets = this.getMyNetworks().reverse();
            var that = this;
            for(var j=0;j<my_nets.length;j++){
                var social_nets = this.getSocialNetworks();
                var tmp_match = null;
                var exists_at = null;
                $.each(social_nets,function(i,val){
                    if(val.name==my_nets[j]){
                        tmp_match = val;
                        social_nets.splice(i,1);
                        social_nets.unshift(val);
                        that.setSocialNetworks(social_nets);
                        return false;
                    }
                });
            };
        },

        getMyNetworks: function(){
            if(my_networks){
                return my_networks;
            }else{
                var my_nets_cookie = CookieManager.get(my_networks_cookie);
                return my_nets_cookie ? my_nets_cookie.split(",") : [];
            }
        },

        setMyNetworks: function(value){
            if(value){
                switch(ViewHelper.trueTypeOf(value)){
                case "array":
                    my_networks = value;
                    CookieManager.set(my_networks_cookie,value.join(","));
                    break;
                case "string":
                    var my_networks = this.getMyNetworks();
                    if(my_networks.length > 0){
                        var exists_at = $.inArray(value,my_networks);
                        if(exists_at != -1){
                            my_networks.splice(exists_at,1);
                            my_networks.unshift(value);
                        }else{
                            my_networks.unshift(value);
                        }
                    }else{
                        my_networks.push(value);
                    }
                    CookieManager.set(my_networks_cookie,my_networks.join(","))
                }
            }
        },

        openSocial: function(url) {
            window.open(url, 'social_bookmarking','toolbar=no,width=700,height=480,resizable=yes,scrollbars=1');
        },

        setSocialNetworkElementHtml: function(element,share_url){
            if(element){
                var social_network_icons = "";
                var article_title = document.title;
                var existing_template = $(".social_icons",element);
                $.each(this.getSocialNetworks(),function(){
                    var tmp_template = new Template(this["url_template"]) || "";
                    var tmp_url = tmp_template.evaluate({shareUrl: share_url, article: article_title}) || "";
                    social_network_icons = social_network_icons + icon_template.evaluate({
                        name: this["name"],
                        class_name: this["class_name"],
                        domain_base: DocumentProperties.getStaticDomain(),
                        url_template: tmp_url
                    });
                });

                element.animate({opacity:0},500,function(){
                    $(this).html(social_network_icons).append("<br clear=\"all\" />");
                    Share.setSocialNetworkClickBehaviors(element);
                });
                setTimeout(function(){element.animate({opacity:1},500)},1000);
            }
        },

        setSocialNetworkClickBehaviors: function(element){
            if(element){
                $("a.social_link",element).unbind('click.social_network').bind('click.social_network',function(e){
                    var doc_url = DocumentProperties.getDocumentUrl();
                    var network_name = $(this).attr("title");
                    var network = $.grep(Share.getSocialNetworks(),function(n,i){
                        return n.name == network_name;
                    })[0];
                    var share_url = 'http://' + DocumentProperties.getCollectionDomain()
                        + DocumentProperties.getDocumentUrl()
                        + escape("?pg=" + PageController.currentPage
                        +"&pm=" + PageModel.pageMode
                        + "&u1=" + PageModel.u1
                        + "&linkImageSrc=" + $(".folio").attr('thumbnail') + "/");
                    if(typeof ArticleViewer != "undefined" && ArticleViewer.active === true && ArticleViewer.article){
                        share_url += escape("&article_id="+ArticleViewer.article.article_id);
                    }
                    var track_page = document.location.protocol + "//" + document.location.host + doc_url + "?t=Share_social&network=" + $(this).attr('title');
                    var url_template = new Template(network.url_template);
                    var url = url_template.evaluate({
                        shareUrl: share_url,
                        article: escape(document.title)
                    });
                    e.preventDefault();
                    Share.openSocial(url);
                    Share.setMyNetworks(network_name);
                    Share.setCustomSocialNetworksOrder();
                    //change this to set html on all icon divs...
                    $(".social_icons").each(function(){
                        Share.setSocialNetworkElementHtml($(this),share_url);
                    });
                    setTimeout(function(){
                        Tracker.trackPage({"category":"share","share_type":"social_network_"+network_name,"pageName":track_page,"title":"Share "+$(this).attr('title'),"lochref":document.location.href});
                    },0);
                });
            }
        },

        collapsibleIcons: (function(){
            var icon_wrapper = {};
            var icon_div = {};
            var icon_div_expander = {};
            var more_icons = {};
            var base_height = 0;

            function toggle_icon_div(e){
                e.preventDefault();
                e.stopPropagation();
                var icon_spans = $(this).siblings(".social_icons").children("span");
                var total_icon_spans = icon_spans.length;
                var icon_w = icon_spans.filter(":first").width();
                var parent_w = $(this).parent().width();
                var icon_rows = Math.ceil((total_icon_spans * icon_w)/parent_w);
                var new_height = $(this).is('.selected') ? base_height : (base_height * icon_rows) ;
                $(this)
                    .toggleClass("selected")
                    .parent().animate({height:new_height},200);
                return false;
            }

            function init_icon_div_expander(){
                icon_div_expander.unbind('click.toggle_icon_div').bind('click.toggle_icon_div',toggle_icon_div);
            }

            function get_icon_div(){
                return icon_div;
            }

            function get_icon_div_expander(){
                return icon_div_expander;
            }

            function get_icon_wrapper(){
                return icon_wrapper;
            }

            return {
                init: function(scope){
                    icon_wrapper = $(".social_icons_wrapper",scope);
                    icon_div = $(".social_icons",icon_wrapper);
                    base_height = ViewHelper.height(icon_wrapper);
                    icon_div_expander = $(".more_icons",icon_wrapper);
                    Share.initSocialNetworkIcons(icon_wrapper);
                    init_icon_div_expander();
                    if(icon_wrapper.parents("#drawer").length){
                       $(Drawer.Model.drawer)
                        .bind('resize_start',Share.collapsibleIcons.drawerResizeStart)
                        .bind('resize_stop',Share.collapsibleIcons.drawerResizeStop);
                    }
                },

                drawerResizeStart: function(e){
                    if(e.size == Constants.fullDrawer){
                        get_icon_wrapper().css("height",base_height+"px");
                        if(get_icon_div_expander().is(".selected")){
                            get_icon_div_expander().removeClass('selected');
                        }
                        get_icon_div().css("text-align","center");
                    }else{
                        get_icon_div().css({textAlign:'left'});
                    }
                    get_icon_div().css('visibility','hidden');
                    get_icon_div_expander().css("display","none");
                },

                drawerResizeStop: function(e){
                    get_icon_div().css("visibility","visible");
                    if(e.size == Constants.standardDrawer){
                        get_icon_div_expander().css("display","block");
                    }
                }
            }
        }())
    }

})();

/* Page Links */
function internalLinkToPage(pg){
    PageController.handleGoToPage(pg);
}



function toPage(){
   var lowestValue = $("#start :selected").val();
   if( parseInt($("#end :selected").val()) < parseInt(lowestValue)) {
       $("#end option[value='"+lowestValue+"']").attr("selected","true");
   }
}



 // Enable/Disable Buttons, based upon current page (DT-4577)
function handleNavigationButtons(page) {
    var pg = page || PageView.currentDisplayedPage;
    var lastPage = PageModel.lastPage;
    if (PageModel.pageMode == 2 && lastPage % 2 == (PageModel.twoPageCover ? 0 : 1)) {
      lastPage -= 1;
    }

    if ((pg == 1) || ((page == 2) &&
            (PageModel.twoPageCover == true) && (PageModel.pageMode == 2))){
        Navbar.Model.firstPageButtons.addClass('hidden');
        Navbar.Model.prevPageButtons.addClass('hidden');
        Navbar.Model.lastPageButtons.removeClass('hidden');
        Navbar.Model.nextPageButtons.removeClass('hidden');
        Navbar.Model.firstPageDisabledButton.removeClass('hidden');
        Navbar.Model.lastPageDisabledButton.addClass('hidden');
        Navbar.Model.nextPageDisabledButton.addClass('hidden');
        Navbar.Model.prevPageDisabledButton.removeClass('hidden');
    }else if (pg >= lastPage){
        Navbar.Model.firstPageButtons.removeClass('hidden');
        Navbar.Model.prevPageButtons.removeClass('hidden');
        Navbar.Model.lastPageButtons.addClass('hidden');
        Navbar.Model.nextPageButtons.addClass('hidden');
        Navbar.Model.firstPageDisabledButton.addClass('hidden');
        Navbar.Model.lastPageDisabledButton.removeClass('hidden');
        Navbar.Model.nextPageDisabledButton.removeClass('hidden');
        Navbar.Model.prevPageDisabledButton.addClass('hidden');
    } else {
        Navbar.Model.firstPageButtons.removeClass('hidden');
        Navbar.Model.prevPageButtons.removeClass('hidden');
        Navbar.Model.lastPageButtons.removeClass('hidden');
        Navbar.Model.nextPageButtons.removeClass('hidden');
        Navbar.Model.firstPageDisabledButton.addClass('hidden');
        Navbar.Model.lastPageDisabledButton.addClass('hidden');
        Navbar.Model.nextPageDisabledButton.addClass('hidden');
        Navbar.Model.prevPageDisabledButton.addClass('hidden');
    }
}


Print = (function(){

    function call_print_action() {
      var start;        // print starting from this page
      var end;       // stop printing on this page
      var invalidRequest=false;  // in the event neither left_page or right_page is selected
      var pageMode = PageModel.pageMode;
      var articleTitle = "";
      var articlePrintMode=false;
      var articlePrintLimitReachedPages="";

      start = (PageController.currentPage % 2 == (PageModel.twoPageCover ? 0 : 1) && pageMode == 2 && PageController.currentPage > 1)  ? PageController.currentPage - 1 : PageController.currentPage;

      if($("input[name='print']:checked").val() == "current"){
         if(pageMode==1){
            end = start;
         }else{
            if($("input[name='left_page']:checked").val() && $("input[name='right_page']:checked").val()){
            // this is the option if both 'left' and 'right' are checked in 2 page mode
                  if(start != 1){
                     end = start + 1;
                  }else{
                     end = start;
                  }
            }else if($("input[name='left_page']:checked").val()) {
            // this is the option if only 'left' is checked in 2 page mode
                  end = start;
            }else if($("input[name='right_page']:checked").val()) {
            // this is the option if only 'right' is checked in 2 page mode
                  if(start != 1){
                     start++;
                  }
                  end = start;
            }else{
            // we're in 2 page mode and neither right nor left was checked...alert the user
                  alert("Invalid print request. Neither page was selected to be printed");
                  invalidRequest = true;
            }
         }
         //check if this page is a article page and has reached the print limit, throw an error
         if (!(invalidRequest)){
            articlePrintLimitReachedPages = $("input[name='articleLimitReachedPages']").val() ;
            var onePageModemsg="Print limit has reached for selected page";
            var msg = "Print limit has reached for one or more pages that you have selected";
            var limitReached=false;
            if (articlePrintLimitReachedPages.indexOf("|" + start + "|") != -1 ){
               limitReached=true;
               //msg = msg + "Page " + start ;
            }
            if (articlePrintLimitReachedPages.indexOf("|" + end + "|") != -1 ){
   //             if (limitReached){
   //                msg = msg + ", Page " + end ;
   //             }else{
   //                msg = msg + " Page " + end ;
   //             }
               limitReached=true;
            }
            if (limitReached && pageMode==1){
               msg = onePageModemsg;
            }
            if (limitReached){
               alert(msg);
                  invalidRequest = true;
            }
         }
      }else if($("input[name='print']:checked").val() == "all")   {
         if($("input[name='articlePrintlimitReached']").val() == "true") {
            //article printing is on for this document and limit has reached on one of the articles...alert the user
            alert("Some of the articles have reached the print limit. Please select individual articles for printing.");
               invalidRequest = true;
         }else{
            start = 1;
               end = $("#end option:last").val() ;
         }
      }else if($("input[name='print']:checked").val() == "subset") {
            toPage();
            start =  $("#start :selected").val();
            end = $("#end :selected").val();
      }else if($("input[name='print']:checked").val() == "article") {
         //toPage();
         start =  -1;
         end = -1;
         articleTitle = getSelectedTitle();
         articlePrintMode=true;

      }

      if(!(invalidRequest)){
          var print_url = DataSwitch.addLmParam(location.pathname+"/Print_submit.action?articleTitle=" + articleTitle + "&articlePrintMode=" + articlePrintMode +"&start=" + start + "&end=" + end + "&prettyPrint=" + $("input[name='prettyPrint']").val());
          $("#button_link_print_dialog").dialog("close");
          var track_url = ViewHelper.formatTrackingUrl(document.location.protocol + "//" + document.location.host + print_url);
          setTimeout(function(){
               Tracker.trackPage({"category":"print","pageName":track_url,"title":"Print "+start+"-"+end,"lochref":document.location.href});
          },0);
          window.open(print_url);
      }
    }
   function hideArticlePrintMsg(){
       $("#print_submit_enabled").show() ;
       $("#article_limit_msg").hide() ;
        $("#article_limit_subscribe").hide() ;
       $("#article_print_limit").hide();
       $("#article_sponsored_msg").hide();
   }
    function print_option(e){
         var target = $(e).attr("id");
         if(target == "print_current") {
              $("#print select").attr("disabled","true");
              $("#print input:checkbox").removeAttr("disabled");
              hideArticlePrintMsg();
         }else if(target == "print_all")  {
              $("#print select").attr("disabled","true");
              $("#print input:checkbox").attr("disabled","true");
              hideArticlePrintMsg();
         }else if(target == "print_subset") {
              $("#print select").removeAttr("disabled");
              $("#print input:checkbox").attr("disabled","true");
              hideArticlePrintMsg();
         }else if(target == "print_article") {
         $("#print select").removeAttr("disabled");
         $("#print input:checkbox").attr("disabled","true");
         $("#prtArticle").selectedIndex = 0;
         setPrintCounter();

         }
    }

    function getSelectedTitle(){
      if ( current_article_title == ""){
         setPrintCounter();
      }

      return current_article_title;

    }

    return {
        init: function(){
            $("#print_submit").unbind('click').click(call_print_action);
            $("#print input:radio").unbind('click').click(function (){ print_option(this);});
            $("#print select").attr("disabled","true");
            $("#article_limit_msg").hide();
            $("#article_limit_subscribe").hide();
         $("#article_sponsored_msg").hide();

        }
    }
})();

Download = (function(){

    function call_download_action(){
        var start_selector = $("#start",$("#download"));
        var end_selector = $("#end",$("#download"));
        var start = PageController.currentPage;
        var download_form = $("form[name='download_form']",$("#download"));
        var download_form_action = download_form.attr("action");

        if($("#download_subset:checked",$("#download")).length){
            start = start_selector.val();
            end = end_selector.val();
            pgs = start + "," + end;
        }else{
            pgs = "all";
        }
        var url = document.location.protocol + "//" + document.location.host + download_form_action;
        if (download_form_action.indexOf('?') >= 0) {
         url = url + "&"
        } else {
         url = url + "?"
        }
        url = url + "pgs=" + pgs;
        $("#button_link_download_dialog").dialog("close");
        setTimeout(function(){
            Tracker.trackPage({"category":"download","download_type":"pdf","pageName":ViewHelper.formatTrackingUrl(url),"title":"Download "+pgs,"lochref":document.location.href});
//            track_downloads("pdf", start);
        },0);
        window.open(url, 'download', 'fullscreen=no, width=600, height=275, resizable=yes, scrollbars=yes, menubar=no, toolbar=no, status=no, location=no');
        return false;
    }

    return {
        init: function(){
            $("#button_link_download_content").height("auto");
            Offline.init();
            var offlineSettings = Offline.getOfflineSettings();
            var download = $("#download");
            if(window.google && window.google.gears){
                $("#gears_installed",download).removeClass("hidden");
            }else{
                $("#gears_not_installed",download).removeClass("hidden");
                var gears_message = $("#gears_message",download).text();
                $("#gears_link",download).bind('click',function(){
                    var doc_url = DocumentProperties.getDocumentUrl();
                    CookieManager.set("download", "true");
                    if($("input.install_shortcut:checked",$("#button_link_download_dialog")).length > 0){
                        CookieManager.set("shouldCreateShortcut","true");
                    }
                    document.location.href = 'http://gears.google.com/?action=install'
                        + '&name=Coverleaf Reader'
                        + '&message=' + encodeURIComponent(gears_message)
                        + '&return=' + encodeURIComponent(window.location.href);
                });
            }
            if(offlineSettings.desktop_shortcut!==true){
                $("input.install_shortcut:visible").attr("checked","checked");
            }
            $("#download_pdf",$("#download")).unbind('click').bind('click',call_download_action);
            $("#download_offline",$("#download")).unbind('click').bind('click',function(){
                Offline.goOffline();
                setTimeout(function(){
                    Tracker.trackPage({"category":"download","download_type":"gears","pageName":document.location.protocol + "//" + document.location.host + DocumentProperties.getDocumentUrl() + "?t=begin_offline_download","title":"Download Offline","lochref":document.location.href});
//                    track_downloads("gears");
                },0);
            });
        }
    }
})();

/**
 * Cross-browser implementation to capture all the html for an element, including the element
 * itself; as opposed to innerHTML which only captures the html included inside the element.
 * outerHTML is supported on some browsers, but not all, so we roll our own.
 *
 * Call as:  var outer = $(element).outerHtml();
 */
$.fn.outerHtml = function() {
    var doc = this[0] ? this[0].ownerDocument : document;
    return $('<div></div>', doc).append(this.eq(0).clone()).html();
};

/*!
 * Escapify JQuery Plugin Library v0.1.0
 * http://www.therubinway.com/escapify
 *
 * Copyright 2010, Alan Rubin
 * Licensed under the MIT license.
 */
(function($){
   
   // Escapify HTML
   $.escapifyHTML = function(text){
       if(text) {
           return $('<div/>').text(text).html();
       } else {
           return text;
       }
   };
   
   // Unescapify HTML
   $.unescapifyHTML = function(text){
       if(text) {
           return $('<div/>').html(text).text();
       } else {
           return text;
       }
   };

})(jQuery);



