///////////////////////////////////////////////////////////////////////////////
// Description: JavaScript to show/hide post content for Blogger blogs
// URI: http://www.meghalomania.com/
// Author: Yumnyum
// Author URI: http://www.meghalomania.com/
// Version: 1.0
///////////////////////////////////////////////////////////////////////////////

// define the hide style
if (document.getElementById)
{
  document.write("<style type=\"text/css\">");
  document.write(".hidepostcontent { display:none; }");
  document.write("</style>");
}

///////////////////////////////////////////////////////////////////////////////
// important constants
///////////////////////////////////////////////////////////////////////////////

// these determine the position at which to cut off display when
// hiding post content.
//
// minLen      the minimum number of characters (including HTML
//             syntax) in the post body that will be visible (i.e.
//             the cutoff - point will be after minLen characters)
//
// minHide     the minimum number of characters (including HTML
//             syntax) in the post body after the cutoff point
//
// If the total number of characters in the post body is less than
// minLen + minHide, then there will be no automatic hiding of content
// for that post.
var minLen = 100;
var minHide = 400;

// display text for show / hide links in the page
var showMoreTxt = "[+] more";
var showLessTxt = "[-] less";

///////////////////////////////////////////////////////////////////////////////
// general utility functions
///////////////////////////////////////////////////////////////////////////////

// concat a string several times
function addStrRepeat(str, count)
{
  var src = "";
  for (var i = 0; i < count; i++)
  {
    src += str;
  }
  return src;
}

// add an indexOf function to the Array class (this does inefficient
// linear search, but for the task at hand it should be sufficient)
if (!Array.prototype.indexOf)
{
  function Array_indexOf(x)
  {
    for (var i = 0; i < this.length; i++)
    {
      if (this[i] == x)
      {
        return i;
      }
    }
    return -1;
  }
  Array.prototype.indexOf = Array_indexOf;
}

///////////////////////////////////////////////////////////////////////////////
// functions to manipulate the post body
///////////////////////////////////////////////////////////////////////////////

// generate the html code that enables user to switch show / hide mode
function writeToggleStr(postid, bShowContent)
{
  var postURL = "#" + postid.substr(4);
  var prefStr = "<a class=\"showhidelink\" href=\"";
  prefStr += postURL;
  prefStr += "\" onclick=javascript:toggleVisible('" + postid + "',";
  var expandStr = prefStr + "true);>" + showMoreTxt + "</a>";
  var collapseStr = prefStr + "false);>" + showLessTxt + "</a>";

  whichpost = document.getElementById(postid);
  children = whichpost.childNodes;
  for (var i = 0; i < children.length; i++)
  {
    if (children[i].tagName == "DIV" && children[i].className == "showhidestring")
    {
      children[i].innerHTML = bShowContent ? collapseStr : expandStr;
      break;
    }
  }
}

// generate the div containing the post text
function getPostBody(postid)
{
  var postBody = null;
  whichpost = document.getElementById(postid);
  children = whichpost.childNodes;
  for (var i = 0; i < children.length; i++)
  {
    if (children[i].tagName == "DIV" && children[i].className == "showhideposttext")
    {
      postBody = children[i];
      break;
    }
  }
  return postBody;
}

// display the code to enable toggling show/hide in a post
function displayToggle(postid)
{
  if (document.getElementById)
  {
    if (limitDisplay(postid))
    {
      writeToggleStr(postid, false);
    }
  }
}

// add the ellipsis and if specified, the hide tag
function addHideStr(postBody, breakPos)
{
  if (breakPos[0] == -1)
  {
    return false;
  }

  var postStr = postBody.innerHTML;

  var dispStr = postStr.substr(0, breakPos[0]);
  var hideStr = postStr.substr(breakPos[0]);

  var newStr = dispStr;
  newStr += "<div class=\"showpostcontent\"> ...</div>";
  //newStr += addStrRepeat("</br>", breakPos[2]);
  //newStr += addStrRepeat("</p>", breakPos[1]);

  if (breakPos[3])
  {
    newStr += "<div class=\"hidepostcontent\">";
    //newStr += addStrRepeat("<p>", breakPos[1]);
    //newStr += addStrRepeat("<br>", breakPos[2]);
    newStr += hideStr + "</div>";
  }
  else
  {
    newStr += hideStr;
  }

  postBody.innerHTML = newStr;
  return true;
}

// find the position in the post body where to cutoff text -- it
// returns an array called breakPos with four elements
//   breakPos[0] -- cutoff position (-1 indicates no cutoff)
//   breakPos[1] -- number of open <p> tags
//   breakPos[2] -- number of open <br> tags
//   breakPos[3] -- flag to indicate whether to add the 'hide content'
//                  div (false means the user might have manually
//                  inserted one, and so we shouldn't be adding
//                  another)
function findBreakPos(postBody)
{
  var breakPos = new Array(-1, 0, 0, false); // break, #p, #br, bAddHideStr

  var postStr = postBody.innerHTML;
  var lowPostStr = postStr.toLowerCase();
  var posHidden = lowPostStr.indexOf("hidepostcontent");
  if (posHidden != -1)
  {
    posHidden = lowPostStr.substr(0, posHidden).lastIndexOf("<div");
  }
  if (posHidden != -1)
  {
    breakPos[0] = posHidden;
    return breakPos;
  }

  var totLen = lowPostStr.length;
  if (totLen < minLen + minHide)
  {
    return breakPos;
  }

  breakPos[3] = true; // add the hide tag
  breakPos[0] = 0;

  var tagsList = new Array();
  while (breakPos[0] < minLen || tagsList.length != 0)
  {
    var curStr = lowPostStr.substr(breakPos[0]);
    var tagPos = curStr.indexOf("<");
    if (tagPos == -1)
    {
      break;
    }

    var remStr = curStr.substr(tagPos + 1);
    var endTagPos = remStr.indexOf(">");
    var closeTagPos = remStr.indexOf("/>");
    var spacePos = remStr.indexOf(" ");
    var namePos = spacePos != -1 && spacePos < endTagPos ? spacePos : endTagPos;
    if (closeTagPos == endTagPos - 1 && namePos == endTagPos)
    {
      namePos--;
    }
    var tagName = remStr.substr(0, namePos);
    var bTagEnd = tagName.indexOf("/") == 0;
    if (bTagEnd)
    {
      tagName = tagName.substr(1);
    }

    if (breakPos[0] + tagPos > minLen && tagsList.length == 0 &&
        (tagName == "p" || tagName == "br"))
    {
      breakPos[0] += tagPos;
      break;
    }

    breakPos[0] += tagPos + endTagPos + 2;

    if (closeTagPos == endTagPos - 1)
    {
      continue;
    }

    if (tagName == "p")
    {
      breakPos[1] += bTagEnd ? -1 : 1;
    }
    else if (tagName == "br")
    {
      breakPos[2] += bTagEnd ? -1 : 1;
    }
    else if (bTagEnd)
    {
      ind = tagsList.indexOf(tagName);
      if (ind != -1)
      {
        tagsList.splice(ind, 1);
      }
    }
    else
    {
      tagsList.push(tagName);
    }
  }

  if (breakPos[0] < minLen || totLen - breakPos[0] < minHide)
  {
    breakPos[0] = -1;
  }

  return breakPos;
}

// hide text starting at the appropriate place

function limitDisplay(postid)

{
  var postBody = getPostBody(postid);
  if (postBody)
  {
    return addHideStr(postBody, findBreakPos(postBody));
  }
  return false;
}

// switch between show and hide mode
function swapStyles(divBody)
{
  var children = divBody.childNodes;
  for (var i = 0; i < children.length; i++)
  {
    if (children[i].tagName == "DIV")
    {
      if (children[i].className == "hidepostcontent")
      {
        children[i].className = "showpostcontent";
      }
      else if (children[i].className == "showpostcontent")
      {
        children[i].className = "hidepostcontent";
      }
    }
  }
}

// main function to change show/hide mode
function toggleVisible(postid, bShowContent)
{
  var postBody = getPostBody(postid);
  if (postBody)
  {
    swapStyles(postBody);
    writeToggleStr(postid, bShowContent);
  }
}

// -->
