// Journal inline size control script.
// ===================================
//
// Add this to the Footer section of your smugmug coustomization.  Then you
// can control the size of inline journal images in a number of different
// ways.
//
//  1. Default gallery rules via CSS.  Add a CSS rule with a name containing
//     one or more of the following:
//
//          JournalSIZERule
//
//     where size is WIDTHxHEIGHT and gives the maximum dimensions of the
//     image. // The image will be made as large as possible while respecting
//     these limits.
//
//     For example, the css rule:
//
//          #Journal600x600Rule {}
//
//     Specifies that images should be as large as possible without either
//     dimension exceeding 600px.
//
//  2. Default gallery rules via the gallery Description.  To do this, specify
//     rules as above in the gallery description.  You can prevent them from
//     being displayed by encasing in spans.  For example:
//
//          <span name="Journal600x600Rule"></span>
//
//     The rules don't all have to be contained in one span name (unlike CSS
//     rules).  If there is at least one such rule in a gallery's Description,
//     the CSS isn't searched for rules and thus it takes precedence over any
//     rules specified there.  In fact, specifying the rules in the gallery
//     Description is essentially a little faster than using CSS.
//
//  3. Individual image rules.  The description of any image can contain a
//     JournalSIZERule.  Use the <span> trick to hide it.  If present, such a
//     rule take s precedence over the above.
//
//  4. Depricated support of specifying Medium or Large as a default and for
//     landscape and/or portrait orientations.  Basically, if you used this
//     before, it should still owrk.  So you can use Small, Medium, or Large
//     in place of the dimension limits above.  Additionally you can use add
//     Portrait or Landscape to specify that the Small, Medium, or Large size
//     only applies to that orientation.  For example
//
//          #JournalMediumRule_JournalPortraitLargeRule {}
//
//     Specifies Medium as teh default but Large for portrait orientaion.
//     rule take s precedence over the above.


var medium_scale = 1.5;
var large_scale = 2.0;
var small_max_height = 300;
var small_max_width = 400;
var medium_max_height = 450;
var medium_max_width = 600;
var large_max_height = 600;
var large_max_width = 800;

var upsize_re = /Journal(Small|Medium|Large)Rule/;
var portrait_resize_re = /JournalPortrait(Small|Medium|Large)Rule/;
var landscape_resize_re = /JournalLandscape(Small|Medium|Large)Rule/;
var custom_resize_re = /Journal(\d+)[xX](\d+)Rule/;

// ScaleRules is a class that has the job of figuring out just what to do with
// each image depending on the various rules present and the dimensions of the
// image.

function ScaleRules()
{
  this.default_rule = "";
  this.portrait_rule = "";
  this.landscape_rule = "";
  this.image_rule = "";
  this.has_custom_size = false;
}

function ScaleRules_hasGalleryRule()
{
  with (this) {
    return has_custom_size || default_rule || portrait_rule || landscape_rule;
  }
}

ScaleRules.prototype.hasGalleryRule = ScaleRules_hasGalleryRule;

function ScaleRules_MaybeSetGalleryRules(str)
{
  if (str) {
    if (custom_resize_re.test(str)) {
      this.has_custom_size = true;
      this.max_width = parseInt(RegExp.$1);
      this.max_height = parseInt(RegExp.$2);
      this.custom_size_string = RegExp.$1 + "x" + RegExp.$2;
    }
    else {
      if (upsize_re.test(str)) {
        this.default_rule = RegExp.$1.charAt(0);
      }
      if (portrait_resize_re.test(str)) {
        this.portrait_rule = RegExp.$1.charAt(0);
      }
      if (landscape_resize_re.test(str)) {
        this.landscape_rule = RegExp.$1.charAt(0);
      }
    }
  }
}

ScaleRules.prototype.maybeSetGalleryRules = ScaleRules_MaybeSetGalleryRules;

function ScaleRules_SetImageRule(str)
{
  this.image_rule = "";
  this.image_has_custom_size = false;
  if (str) {
    if (custom_resize_re.test(str)) {
      this.image_has_custom_size = true;
      this.image_max_width = parseInt(RegExp.$1);
      this.image_max_height = parseInt(RegExp.$2);
      this.image_custom_size_string = RegExp.$1 + "x" + RegExp.$2;
    }
    else if (upsize_re.test(str)) {
      this.image_rule = RegExp.$1.charAt(0);
    }
  }
}

ScaleRules.prototype.setImageRule = ScaleRules_SetImageRule;


function ScaleRules_CalculateScale(height,max_height,width,max_width,
                                   size_string)
{
  var height_scale = max_height / height;
  var width_scale = max_width / width;
  // Optimization, we'll use SM S,M,L images if they happen to be the right
  // size (and we can be sure of it!  Because of the change in L size in 2006,
  // we have to be careful about L
  if (height_scale < width_scale) {
    this.scale = height_scale;
    if (max_height == small_max_height)
      this.image_size_string = "S";
    else if (max_height == medium_max_height)
      this.image_size_string = "M";
    else
      this.image_size_string = size_string;
  }
  else {
    this.scale = width_scale;
    if (max_width == small_max_width)
      this.image_size_string = "S";
    else if (max_width == medium_max_width)
      this.image_size_string = "M";
    else if (max_width == large_max_width)
      this.image_size_string = "L";
    else
      this.image_size_string = size_string;
  }
}

ScaleRules.prototype.calculateScale = ScaleRules_CalculateScale;

scale_table = {'M': medium_scale, 'L': large_scale, 'S': 1};

function ScaleRules_SetImageSize(height,width)
{
  this.image_height = height;
  this.image_width = width;

  this.image_size_string = 'S';

  // Backward compatibility (mixing L,M and YxZ rules) makes this more hairy
  // than we'd like

  if (height == small_max_height || width == small_max_width) {
    if (this.image_has_custom_size) {
      this.calculateScale(height,this.image_max_height,
                          width,this.image_max_width,
                          this.image_custom_size_string);
    }
    else if (this.image_rule != "") {
      this.image_size_string = this.image_rule;
      this.scale = scale_table[this.image_size_string];
    }
    else if (this.has_custom_size) {
      this.calculateScale(height,this.max_height,
                          width,this.max_width,
                          this.custom_size_string);
    }
    else {
      if (this.portrait_rule != "" && height > width) {
        this.image_size_string = this.portrait_rule;
      }
      else if (this.landscape_rule != "" && height < width) {
        // Landscape
        this.image_size_string = this.landscape_rule;
      }
      else if (this.default_rule != "") {
        this.image_size_string = this.default_rule;
      }
      this.scale = scale_table[this.image_size_string];

      // Ugh, smugmug changed the meaning of L, so we have to be on our toes
      // about this.  Anything over 600px high, we can't tell if it's L or
      // not.  (uploads before a certain date are, after not).  So if we can't
      // know, we'll use the explicit custom size that corresponds to current
      // smugmug L.
      if (this.image_size_string == "L")
        this.calculateScale(height,600,width,800,"600x800");
        
    }
  }
}

ScaleRules.prototype.setImageSize = ScaleRules_SetImageSize;

function ScaleRules_ImageHeight()
{
  return Math.round(this.image_height * this.scale);
}

ScaleRules.prototype.imageHeight = ScaleRules_ImageHeight;

function ScaleRules_ImageWidth()
{
  return Math.round(this.image_width * this.scale);
}

ScaleRules.prototype.imageWidth = ScaleRules_ImageWidth;


function upsize_image(img, prefix, suffix, img_num, rule) {
  var caption = document.getElementById('caption'+img_num);
  if (caption)
    rule.setImageRule(caption.innerHTML);
  else
    rule.setImageRule("");
    
  rule.setImageSize(img.height,img.width);
    if (rule.scale != 1) {                              
    img.src = prefix + rule.image_size_string + suffix;
    img.height = rule.imageHeight();
    img.width = rule.imageWidth();
  }
}

function upsize_journal_entry(div,rule) {
  var imgs = div.getElementsByTagName('IMG');
  var re = /(http:\/\/[^\/]*\/photos\/(\d+)-)S((-\d+)?.jpg)/
    for(var i=0; i<imgs.length; i++) {
      if(re.test(imgs[i].src)) {
        upsize_image(imgs[i], RegExp.$1, RegExp.$3, RegExp.$2, rule);
      }
    }
}

function upsize_journal_entries(rule) {
  var divs = document.getElementsByTagName('DIV');
  for (var i=0; i<divs.length; i++) {
    if (divs[i].className=='journal_entry') {
      upsize_journal_entry(divs[i], rule);
    }
  }
}

function isClass(sClass) {
  var sClassName = document.body.className;
  var re = new RegExp(sClass + "( |$)")
    if (!sClassName)
      return false;
  return re.test(sClassName);
}

function maybe_resize() {
  if (isClass("journal")) {
    var rule = new ScaleRules();

    var description = document.getElementById('albumDescription');
    if (description)
      rule.maybeSetGalleryRules(description.innerHTML);
    if (! rule.hasGalleryRule())
      rule.maybeSetGalleryRules("Journal800x600Rule");

    upsize_journal_entries(rule);
  }
}