var totype=function(obj) {
  return ({}).toString.call(obj).match(/\s([a-zA-Z]+)/)[1].toLowerCase();
};

function htmlise(s) {
  s=s.toString();
  s=s.replace(/&/g, '&amp;');
  s=s.replace(/</g, '&lt;');
  s=s.replace(/>/g, '&gt;');
  s=s.replace(/"/g, '&quot;');
  return s;
}

function is_id(id) {
  return id.match(/^[a-z][a-z0-9:._-]*/i);
}

function isDef(o) {
  return typeof(o)!='undefined';
}
function isStr(o) {
  return typeof(o)=='string';
}
function isBool(o) {
  return typeof(o)=='boolean';
}

function getById(id) {
  if(!isStr(id))
    return id;
  if(document.getElementById)
    return document.getElementById(id);
  if(document.all)
    return document.all[id];
  return null;
}

function getByClass(classname, node, tag) {
  if(node==null)
    node=document;
  if(tag==null)
    tag='*';
  var elements=new Array();
  var idx=0;
  var e=node.getElementsByTagName(tag);
  var re=new RegExp("(^|\\s)"+classname+"(\\s|$)");
  for(var i=0; i<e.length; i++) {
    if(re.test(e[i].className)) {
      elements[idx]=e[i];
      idx++;
    }
  }
  return elements;
}

function getByTagName(tag, node) {
  if(node==null)
    node=document;
  return node.getElementsByTagName(tag);
}

function hasClass(node, classname) {
  var re=new RegExp("(^|\\s)"+classname+"(\\s|$)");
  return re.test(node.className);
}

function addClass(node, classname) {
  var re=new RegExp("(^|\\s)"+classname+"(\\s|$)");
  if(!re.test(node.className))
    node.className+=(node.className ? ' ' : '')+classname;
}

function delClass(node, classname) {
  var re=new RegExp("(^|\\s)"+classname+"(\\s|$)", 'g');
  if(node.className)
    node.className=trim_inside(node.className.replace(re, ' '));
}

function redirect(url) {
  document.location=url;
}

function focus_first_input(form) {
  if(!form)
    form='default';
  $(document).ready(function() {
    document.forms[form].elements[0].focus();
  });
}

function quash_double_submission(message, form) {
  if(!form)
    form='default';
  $(document).ready(function() {
    $(document.forms[form]).submit(function() {
      if(!this.ext_form_submitted) {
        this.ext_form_submitted=true;
        return true;
      }
      alert(message);
      return false;
    });
  });
}

function donation_go_back() {
  document.forms['default'].elements['back'].value='true';
  document.forms['default'].submit();
  return false;
}

function decimals(n, d) {
  if(d<1)
    return Math.round(n);
  var p=Math.pow(10, d);
  n=Math.round(n*p)/p;
  var fl=Math.floor(n);
  var cents=Math.round((n-fl)*p).toString();
  while(cents.length<d)
    cents+='0';
  return fl.toString()+'.'+cents;
}
String.prototype.decimals=function(d) {
  return decimals(this, d);
};
Number.prototype.decimals=function(d) {
  return decimals(this, d);
};

String.prototype.price=function(d) {
  return '$'+this.decimals(0).encomma();
};
Number.prototype.price=function(d) {
  return '$'+this.decimals(0).encomma();
};

function encomma(n) {
  if(!n)
    return '0';
  n=''+n;
  while(n.match(/^[^.]*\d{4}(?:\.|,|$)/))
    n=n.replace(/^([^.]*\d)(\d{3})(\.|,|$)/, '$1,$2$3');
  return n;
}
String.prototype.encomma=function() {
  return encomma(this);
};
Number.prototype.encomma=function() {
  return encomma(this);
};

function zeropad(n, l) {
  n=''+n;
  while(n.length<l)
    n='0'+n;
  return n;
}
String.prototype.zeropad=function(l) {
  return zeropad(this, l);
};
Number.prototype.zeropad=function(l) {
  return zeropad(this, l);
};

function trim(string) {
  return string.replace(/^\s+/, '').replace(/\s+$/, '');
}
String.prototype.trim=function() {
  return trim(this);
};

function trim_inside(string) {
  return string.trim().replace(/\s{2,}/g, ' ');
}
String.prototype.trim_inside=function() {
  return trim_inside(this);
};

function toggle_blocks() {
  var message='';
  var matchclass=new RegExp("^(show|hide)if(not)?-([^=\\s]+)=(\\S*)$");
  var blocks=getByClass("(show|hide)if(not)?-\\S+");
  for(var i=0; i<blocks.length; i++) {
    var show='undef';
    var classes=blocks[i].className.split(/\s+/);
    for(var j=0; j<classes.length; j++) {
      var matches=matchclass.exec(classes[j]);
      if(matches) {
        var type=matches[1];
        var want=matches[2] ? false : true;
        var control=matches[3];
        var value=matches[4];
        message+=control+' '+type+' '+value+'\n';
        if(show=='undef')
          show=type=='hide';
        var obj=getById(control);
        var button;
        if(obj && obj.tagName=='SELECT') { // workaround for IE
          if((obj.options[obj.selectedIndex].value==value)==want)
            show=type!='hide';
        } else if((button=getById(control+'='+value))) {
          if((button && button.checked)==want)
            show=type!='hide';
        } else if(obj) {
          if((obj.value.trim()==value)==want)
            show=type!='hide';
        }
      }
    }
    if(show && show!='undef') {
      var display;
      if(blocks[i]._toggle_blocks)
        display=blocks[i]._toggle_blocks;
      else {
        var tag=blocks[i].tagName;
        if(tag=='SPAN')
          display='inline';
        else if(tag=='TR')
          display='table-row';
        else if(tag=='TD' || tag=='TH')
          display='table-cell';
        else
          display='block';
      }
      try {
        blocks[i].style.display=display;
      } catch(e) {
        blocks[i].style.display='block'; // IE doesn't understand table-*
      }
    } else {
      if(blocks[i].style.display && blocks[i].style.display!='none')
        blocks[i]._toggle_blocks=blocks[i].style.display;
      blocks[i].style.display='none';
    }
  }
}


//############################################################################
//# Floaters

function create_floater(object, floaterid, o) {
  $(document).ready(function() {
    o=$.extend({
      off_horiz: 10,
      off_vert: 10,
      loading_html: 'Loading...',
      type: 'GET'
    }, o);
    var loaded=false;
    // Note: the iframe is a fix for IE, which otherwise renders select
    // boxes overtop of the modal window.
    var iframeid=floaterid+'-iframe';
    var iframeobj=$('#'+iframeid);
    if(iframeobj.length==0) {
      $(document.body).append('<iframe id="'+iframeid+'"/>');
      iframeobj=$('#'+iframeid);
      iframeobj.css({
          'background-color': '#ffffff',
          border: 'none',
          position: 'absolute',
          display: 'inline',
          'z-index': 10
        })
        .addClass('floater-iframe')
        .hide();
    }
    var floaterobj=$('#'+floaterid);
    if(floaterobj.length==0) {
      floaterobj=$('<div id="'+floaterid+'"/>')
        .appendTo('body')
        .css({
          'background-color': '#ffffff',
          position: 'absolute',
          display: 'inline',
          'z-index': 20
        })
        .addClass('floater')
        .hide()
        .html('<div class="floater-loading-message">'+o.loading_html+'</div>');
    }
    function showatmouse(e) {
      var top=e.pageY+o.off_vert;
      var left=e.pageX+o.off_horiz;
      if(top+floaterobj.height()-$(window).scrollTop()>$(window).height()) {
        top=e.pageY-o.off_vert-floaterobj.height();
        if(top-$(window).scrollTop()<0)
          top=$(window).scrollTop();
      }
      if(left+floaterobj.width()-$(window).scrollLeft()>$(window).width()) {
        left=e.pageX-o.off_vert-floaterobj.width();
        if(left-$(window).scrollLeft()<0)
          left=$(window).scrollLeft();
      }
      $(iframeobj).css({
        top: top+'px',
        left: left+'px',
        width: $(floaterobj).width(),
        height: $(floaterobj).height()
      }).show();
      $(floaterobj).css({
        top: top+'px',
        left: left+'px'
      }).show();
      return false;
    }
    function killfloater(e) {
      $(object).unbind('mousemove', showatmouse);
      $(object).unbind('mouseout', killfloater);
      $('body').unbind('mousemove', killfloater);
      $(floaterobj).hide();
      $(iframeobj).hide();
      return false;
    }

    $(object).bind('mouseover', function(e) {
      e.preventDefault();
      $('.floater').hide();
      $('.floater-iframe').hide();
      showatmouse(e);
      $(object).bind('mousemove', showatmouse);
      $(object).bind('mouseout', killfloater);
      $('body').bind('mousemove', killfloater);
      if(!loaded) {
        loaded=true;
        if(o.content) {
          $(floaterobj).html(o.content);
          showatmouse(e);
        } else {
          var ajaxopts={
            type: o.type,
            url: o.url,
            data: o.data,
            success: function(msg) {
              $(floaterobj).html(msg);
              showatmouse(e);
            }
          };
          $.ajax(ajaxopts);
        }
      }
      return false;
    });
  });
}


//############################################################################
//# Modal utility functions

function loading_message(message) {
  return $('<div class="feed-loading-message">'+message+'</div>');
}

// Slide in content in a way that still manages to run any javascript in it
function replace_slide(target, html, slide_speed) {
  var newdiv=$('<div>');
  if(slide_speed)
    newdiv.hide();
  newdiv.get(0).innerHTML=html; // note: newdiv.html(html) does not always work in IE
  target.replaceWith(newdiv);
  if(slide_speed)
    newdiv.slideDown(slide_speed);
}


//############################################################################
//# Member profile modal

function member_profile(id, memberID, o) {
  if(memberID && is_id(id)) {
    $(document).ready(function() {
      o=$.extend({
        url: '/code/modal/member_profile.php',
        data: 'memberID='+encodeURIComponent(memberID)
      }, o);
      $('#member-profile-trigger-'+id).each(function() {
        create_floater(this, 'member-profile-floater-'+memberID, o);
      });
    });
  }
}


//############################################################################
//# Sponsorship modal

function sponsorship_pending(type, focus, output) {
  output=$(output);
  if(output.length) {
    output.html('');
    if(focus) {
      $.ajax({
        type: 'POST',
        url: '/code/modal/sponsorship_pending.php',
        data: 'type='+encodeURIComponent(type)+'&focus='+encodeURIComponent(focus),
        success: function(msg) {
          output.html(msg);
        }
      });
    }
  }
}


//############################################################################
//# Member and org modals

function verify_member(input, output) {
  input=$(input);
  output=$(output);
  if(input.length && output.length)
    if(!input.val().length)
      alert('Please type the member ID.');
    else {
      output.html('Verifying, please wait...');
      output.show();
      $.ajax({
        type: 'POST',
        url: '/code/modal/verify_member.php',
        data: 'memberID='+encodeURIComponent(input.val()),
        success: function(msg) {
          output.html(msg);
        }
      });
    }
}

function verify_org(input, output) {
  input=$(input);
  output=$(output);
  if(input.length && output.length)
    if(!input.val().length)
      alert('Please type the organization ID.');
    else {
      output.html('Verifying, please wait...');
      output.show();
      $.ajax({
        type: 'POST',
        url: '/code/modal/verify_org.php',
        data: 'orgID='+encodeURIComponent(input.val()),
        success: function(msg) {
          output.html(msg);
        }
      });
    }
}

function search_org(state, name, output, field, o) {
  o=$.extend({
    exclude: false,
    sponsorship_pending: false,
    template: "modal/search_org.html"
  }, o);
  state=$(state);
  name=$(name);
  output=$(output);
  if(state.length && name.length && output.length)
    if(!state.val().length || !name.val().length)
      alert('Please select a state and type a full or partial church name first!');
    else {
      output.html('Searching, please wait...');
      output.show();
      $.ajax({
        type: 'POST',
        url: '/code/modal/search_org.php',
        data: 'state='+encodeURIComponent(state.val())+'&name='+encodeURIComponent(name.val())+'&field='+encodeURIComponent(field)+'&exclude='+encodeURIComponent(o.exclude)+(o.sponsorship_pending ? '&sponsorship_pending=true' : '')+'&template='+encodeURIComponent(o.template),
        success: function(msg) {
          output.html(msg);
        }
      });
    }
}


//############################################################################
//# Location inputs

function location_input_setup(locations, country, state, o) {
  (function($) {
    $(document).ready(function() {
      o=$.extend({
        'location/state/no_country': 'Please select country first',
        'location/state/not_required': 'Not required',
        'location/state/select': 'Please select',
        'fixed_country': false
      }, locations.o, o);
      if(!country)
        country='country_code';
      if(!state)
        state='state';
      country=getById(country);
      state=getById(state);
      if((country || o.fixed_country) && state) {
        var changefunc=function() {
          var countryval=o.fixed_country ? o.fixed_country : country.options[country.selectedIndex].value;
          var stateval=state.options[state.selectedIndex].value;
          state.options.length=0;
          if(!countryval) {
            state.options[0]=new Option(o['location/state/no_country'], '');
            //state.disabled=true;
          } else if(!locations.countries[countryval]) {
            state.options[0]=new Option(o['location/state/not_required'], '');
            //state.disabled=true;
          } else {
            state.options[0]=new Option(o['location/state/select'], '');
            for(var i in locations.countries[countryval]) {
              state.options[state.options.length]=new Option(locations.countries[countryval][i], i);
              if(i==stateval)
                state.selectedIndex=state.options.length-1;
            }
            //state.disabled=false;
          }
        };
        if(!o.fixed_country)
          $(country).change(changefunc);
        changefunc();
      }
    });
  })(jQuery);
}


//############################################################################
//# Scripture version inputs

function scripture_version_input_setup(versions, language, version) {
  (function($) {
    $(document).ready(function() {
      if(!language)
        language='scripture_language';
      if(!version)
        version='scripture_version';
      language=getById(language);
      version=getById(version);
      if(language && version) {
        var changefunc=function() {
          var languageval=language.options[language.selectedIndex].value;
          var versionval=version.options[version.selectedIndex].value;
          version.options.length=0;
          if(versions[languageval]) {
            for(var i in versions[languageval]) {
              version.options[version.options.length]=new Option(versions[languageval][i], i);
              if(i==versionval)
                version.selectedIndex=version.options.length-1;
            }
          } else
            version.options[0]=new Option('Any version is fine', '');
          if(version.options.length<=1)
            $(version).hide();
          else
            $(version).show();
        };
        $(language).change(changefunc);
        changefunc();
      }
    });
  })(jQuery);
}


//############################################################################
//# Comments modal

function setup_comment_feed(table, id, prompt_text, show_edit_link) {
  (function($) {
    var comments, area;
    if(!prompt_text) prompt_text='';
    function _setup_comment_feed(table, id, prompt_text) {
      if((comments=$('#comment-feed-'+table+id).eq(0)).length
        && (area=comments.find('.comment-feed-area').eq(0)).length) {
        function ajax_loader(action, comment, edit) {
          var data='table='+encodeURIComponent(table)+'&ID='+encodeURIComponent(id);
          if(show_edit_link)
            data+='&show_edit_link=true';
          if(action=='like')
            data+='&action=like&comment='+(comment ? 'true' : '');
          else if(action=='delete')
            data+='&action=comment&comment=&edit='+encodeURIComponent(comment);
          else if(action=='comment') {
            data+='&action=comment&comment='+encodeURIComponent(comment);
            if(edit)
              data+='&edit='+encodeURIComponent(edit);
          } else
            data+='&all=true';
          $.ajax({
            type: 'POST',
            url: '/code/modal/comment_feed.php',
            data: data,
            success: function(msg) {
              comments.html(msg);
              _setup_comment_feed(table, id, prompt_text);
            },
            error: function(request, text, error) {
              comments.html('ERROR: '+text);
            }
          });
        }
        var form, input_div, input, submit_div;
        if((form=comments.find('.comment-form').eq(0)).length
          && (input_div=form.find('.comment-input').eq(0)).length
          && (input=input_div.find('textarea').eq(0)).length
          && (submit_div=form.find('.comment-submit').eq(0)).length) {
          input.focus(function() {
            if(!input.val().length || input.val()==prompt_text || input.val().match(/^\s+$/)) {
              form.get(0).elements['edit'].value='';
              input.val('');
            }
            input_div.removeClass('collapsed');
            input_div.addClass('expanded');
            submit_div.show();
          });
          input.blur(function() {
            if(!input.val().length || input.val().match(/^\s+$/)) {
              form.get(0).elements['edit'].value='';
              input.val(prompt_text);
              input_div.removeClass('expanded');
              input_div.addClass('collapsed');
              submit_div.hide();
            }
          });
          form.submit(function(event) {
            event.preventDefault();
            if(input.val().length && input.val()!=prompt_text && !input.val().match(/^\s+$/)) {
              ajax_loader('comment', input.val(), form.get(0).elements['edit'].value);
            }
            return false;
          });
        }
        comments.find('.comment-feed-like').click(function() {
          ajax_loader('like', true);
          return false;
        });
        comments.find('.comment-feed-unlike').click(function() {
          ajax_loader('like', false);
          return false;
        });
        if(input) {
          comments.find('.comment-feed-cancel').click(function() {
            form.get(0).elements['edit'].value='';
            input.val(prompt_text);
            input_div.removeClass('expanded');
            input_div.addClass('collapsed');
            submit_div.hide();
            return false;
          });
          comments.find('.comment-feed-comment').click(function() {
            form.get(0).elements['edit'].value='';
            input.val('');
            input.focus();
            return false;
          });
          comments.find('.comment-edit').click(function() {
            input.focus();
            form.get(0).elements['edit'].value=this.id.replace(/.*-/, '');
            input.val(this.title);
            return false;
          });
        }
        comments.find('.comment-feed-all').click(function() {
          ajax_loader();
          return false;
        });
        comments.find('.comment-delete').click(function() {
          if(confirm('Are you sure you want to delete your comment?'))
            ajax_loader('delete', this.id.replace(/.*-/, ''));
          return false;
        });
      }
    }
    $(document).ready(function() {
      _setup_comment_feed(table, id, prompt_text);
    });
  })(jQuery);
}


//############################################################################
//# Story feed modal

function get_story_feed_container(id) {
  if(is_id(id)) {
    var div=$('#'+id).eq(0);
    if(div.length)
      return div;
  }
  return false;
}

// Set up a story feed exclusive of others on the page, with a link to
// trigger it.  The first feed is open unless o.open_first is set
// false.
function exclusive_story_feed(trigger, id, params, o) {
  o=$.extend({
    open_first: true,
    hide_trigger: true,
    slide_speed: 'slow',
    loading_message: 'Loading, please wait...'
  }, o);
  var container=get_story_feed_container(id);
  if(container && is_id(trigger) && (trigger=$('#'+trigger)).length) {
    var open=o.open_first && !$('.story-feed-triggered').length;
    trigger.addClass('story-feed-trigger');
    container.addClass('story-feed-triggered');
    var anchor;
    if(trigger.is('a'))
      anchor=trigger;
    else
      anchor=trigger.find('a');
    function clickfunc() {
      $('.story-feed-triggered').empty();
      if(o.hide_trigger) {
        $('.story-feed-trigger').show();
        trigger.hide();
      }
      story_feed(id, params, o);
      return false;
    }
    anchor.click(clickfunc);
    if(open)
      clickfunc();
  }
  return false;
}

// Initially load a story feed
function story_feed(id, params, o) {
  $(document).ready(function() {
    o=$.extend({
      slide_speed: 'slow',
      loading_message: 'Loading, please wait...'
    }, o);
    var container=get_story_feed_container(id);
    if(container) {
      var loading=loading_message(o.loading_message);
      container.html(loading);
      $.ajax({
        type: 'POST',
        url: '/code/modal/story_feed.php',
        data: params,
        success: function(msg) {
          replace_slide(loading, msg, o.slide_speed);
        }
      });
    }
  });
  return false;
}

// Set up new story feed
function setup_story_feed(id, params_base, params_search, o) {
  $(document).ready(function() {
    o=$.extend({
      slide_speed: 'slow',
      minimum_length: 20,
      length_error: 'Sorry, your story is too short. Please tell us a little more.',
      posting_message: 'Posting, please wait...',
      searching_message: 'Searching, please wait...'
    }, o);
    var container, feed;
    if((container=get_story_feed_container(id)) && (feed=container.find('.story-feed')).length) {

      // Set up post form
      container.find('.story-feed-post').each(function() {
        var form=$(this);
        form.submit(function() { return false; });
        var input=form.find('.story-feed-post-input');
        var textarea=input.find('textarea');
        var buttons=form.find('.story-feed-post-buttons');
        var submit=form.find('.story-feed-post-submit');
        function story_post_cancel() {
          textarea.val(o.post_prompt);
          input.removeClass('expanded');
          input.addClass('collapsed');
          buttons.hide();
          return false;
        }
        textarea.focus(function() {
          if(!textarea.val().length || textarea.val()==o.post_prompt || textarea.val().match(/^\s+$/))
            textarea.val('');
          input.removeClass('collapsed');
          input.addClass('expanded');
          buttons.show();
        });
        textarea.blur(function() {
          if(!textarea.val().length || textarea.val().match(/^\s+$/))
            story_post_cancel();
        });
        submit.click(function() {
          var body=textarea.val().trim();
          if(!body.length || (o.minimum_length && body.length<o.minimum_length))
            alert(o.length_error);
          else {
            story_post_cancel();
            var loading=loading_message(o.posting_message);
            feed.prepend(loading);
            $.ajax({
              type: 'POST',
              url: '/code/modal/story_feed.php',
              data: params_base+'&'+params_search+'&'+'data[post]=true&data[body]='+encodeURIComponent(body)+'&',
              success: function(msg) {
                replace_slide(loading, msg, o.slide_speed);
              }
            });
          }
          return false;
        });
        form.find('.story-feed-post-cancel').click(story_post_cancel);
      });

      // Set up search form
      container.find('.story-feed-search').each(function() {
        var form=$(this);
        form.submit(function() { return false; });
        var search=form.find('.story-feed-search-search');
        var keywordID=form.find('.story-feed-search-keywordID');
        var date1=form.find('.story-feed-search-date1');
        var date2=form.find('.story-feed-search-date2');
        var sort=form.find('.story-feed-search-sort');
        var submit=form.find('.story-feed-search-submit');
        submit.click(function() {
          var loading=loading_message(o.searching_message);
          container.html(loading);
          $.ajax({
            type: 'POST',
            url: '/code/modal/story_feed.php',
            data: params_base+'&data[search]='+encodeURIComponent(search.val())+(keywordID.length ? '&data[keywordID]='+encodeURIComponent(keywordID.val()) : '')+'&data[date1]='+encodeURIComponent(date1.val())+'&data[date2]='+encodeURIComponent(date2.val())+'&data[sort]='+encodeURIComponent(sort.val()),
            success: function(msg) {
              replace_slide(loading, msg, o.slide_speed);
            }
          });
          return false;
        });
      });
    }
  });
  return false;
}

// Set up story modal continue link
function setup_story_feed_continue(id, params, offset, o) {
  $(document).ready(function() {
    o=$.extend({
      slide_speed: 'slow',
      loading_message: 'Loading, please wait...'
    }, o);
    var container;
    if((container=get_story_feed_container(id))) {
      var div=container.find('.story-feed-continue');
      div.find('a').click(function() {
        var loading=loading_message(o.loading_message);
        div.replaceWith(loading);
        $.ajax({
          type: 'POST',
          url: '/code/modal/story_feed.php',
          data: params+'&data[offset]='+encodeURIComponent(offset),
          success: function(msg) {
            replace_slide(loading, msg, o.slide_speed);
          }
        });
        return false;
      });
    }
  });
  return false;
}

// Set up story modal individual story
function setup_story(id, storyid, params, o) {
  var divid=id+'-story-'+storyid;
  if(is_id(divid)) {
    $(document).ready(function() {
      o=$.extend({
        slide_speed: 'slow',
        minimum_length: 20,
        length_error: 'Sorry, your story is too short. Please tell us a little more.',
        saving_message: 'Saving your changes, please wait...',
        delete_prompt: 'Are you certain you wish to permanently delete your post?'
      }, o);
      $('#'+divid).each(function() {
        var story=$(this);
        var edit=story.find('.comment-feed-edit');
        var story_body=story.find('.story-body');
        var form=story.find('.story-edit');
        var textarea=form.find('textarea');
        var submit=form.find('.story-edit-submit');
        var cancel=form.find('.story-edit-cancel');
        var del=form.find('.story-edit-delete');
        var body=textarea.val();
        form.submit(function() { return false; });
        if(edit.length && textarea.length && submit.length) {
          cancel.click(function() {
            form.hide();
            textarea.val(body);
            story_body.show();
            return false;
          });
          edit.click(function() {
            story_body.hide();
            form.show();
            textarea.focus();
            return false;
          });
          submit.click(function() {
            body=textarea.val().trim();
            if(!body.length || (o.minimum_length && body.length<o.minimum_length))
              alert(o.length_error);
            else {
              var loading=loading_message(o.saving_message);
              story.replaceWith(loading);
              $.ajax({
                type: 'POST',
                url: '/code/modal/story_feed.php',
                data: params+'&data[post]=true&data[edit]='+encodeURIComponent(storyid)+'&data[body]='+encodeURIComponent(body),
                success: function(msg) {
                  replace_slide(loading, msg, o.slide_speed);
                }
              });
            }
            return false;
          });
          del.click(function() {
            if(confirm(o.delete_prompt)) {
              story.remove();
              $.ajax({
                type: 'POST',
                url: '/code/modal/story_feed.php',
                data: params+'&data[post]=true&data[delete]='+encodeURIComponent(storyid)
              });
            }
            return false;
          });
        }
      });
    });
  }
  return false;
}


//############################################################################
//# Formbox (signup etc)

function formbox_setup(id, fields) {
  $(document).ready(function() {
    var formbox=$('#'+id).eq(0);
    if(formbox) {
      function _formbox_setup() {
        formbox.find('input, select').each(function() {
          var input=$(this);
          var inputid=input.attr('id');
          if(inputid)
            inputid=inputid.replace(/^input-/, '');
          var group=input.parents('.group').eq(0);
          if(group && inputid) {
            var tooltip=group.find('#tooltip-'+inputid).eq(0);
            var notify=group.find('#notify-'+inputid).children('div').eq(0);
            var errormsg=group.find('#errormsg-'+inputid).eq(0);
            function formbox_error(o, type) {
              if(!type) type='error';
              notify.attr('class', 'notify-'+type);
              if(errormsg && o['error'])
                errormsg.html('<div>'+o['error']+'</div>');
            }
            function formbox_ok() {
              notify.attr('class', 'notify-ok');
            }
            var check={
              required: function(o) {
                var empty=!input.val().trim().length;
                var target;
                if(o['depends'] && (target=$('#input-'+o['depends']).eq(0)))
                  if(empty && !target.val().trim().length)
                    return 'stop';
                return empty ? 'error' : false;
              },
              integer: function(o) {
                return input.val().trim().match(/^\d*$/) ? false : 'error';
              },
              same: function(o) {
                var target;
                if((target=$('#input-'+o['target']).eq(0)))
                  return input.val().trim()==target.val().trim() ? false : 'error';
                return false;
              },
              email: function(o) {
                return input.val().trim().match(/^[a-z0-9!#$%&\'*+\/=?^_`{|}~.-]+@[a-z0-9]+\.[a-z0-9._-]*[a-z0-9]$/i) ? false : 'error';
              },
              email_typo: function(o) {
                var email=input.val().trim();
                var target=$('#'+o['target']).eq(0);
                if(target) {
                  for(var match in o['typos']) {
                    var re=new RegExp('(@|\\.)'+match.replace(/\./, '\\.')+'$');
                    if(email.match(re)) {
                      var replacement=email.replace(re, '$1'+o['typos'][match]);
                      var yes=target.find('.email-replace-yes').eq(0);
                      var no=target.find('.email-replace-no').eq(0);
                      function replace_yes() {
                        input.val(replacement);
                        unbind();
                        target.hide();
                        formbox_ok();
                      }
                      function replace_no() {
                        unbind();
                        target.hide();
                        formbox_ok();
                      }
                      function unbind() {
                        yes.unbind('click', replace_yes);
                        no.unbind('click', replace_no);
                      }
                      target.find('.email-replacement').html(replacement);
                      yes.attr('checked', false);
                      no.attr('checked', false);
                      yes.click(replace_yes);
                      no.click(replace_no);
                      target.show();
                      return 'warning';
                    }
                  }
                  target.hide();
                }
                return false;
              },
              username: function(o) {
                var val=input.val().trim();
                return val.length>=6 && val.length<=20 && val.match(/^[a-z][a-z0-9_-]*$/i) ? false : 'error';
              },
              password: function(o) {
                return input.val().trim().length>=6 ? false : 'error';
              },
              member: function(o) {
                notify.attr('class', 'notify-loading');
                $.ajax({
                  type: 'POST',
                  url: '/code/modal/check_duplicate.php',
                  data: 'check='+encodeURIComponent(input.val().trim()),
                  success: function(msg) {
                    if(!msg.length!=!o['exists'])
                      formbox_error(o);
                    else
                      formbox_ok();
                  }
                });
                return 'stop';
              }
            };
            input.focus(function() {
              if(input.attr('tagName')!='SELECT')
                input.addClass('active');
              if(tooltip) tooltip.fadeIn('fast');
              if(notify) notify.attr('class', '');
              if(errormsg) errormsg.html('');
            });
            input.blur(function() {
              if(input.attr('tagName')!='SELECT')
                input.removeClass('active');
              if(tooltip) tooltip.hide();
              if(notify && fields[inputid] && (fields[inputid]['required'] || input.val().trim().length)) {
                var error_result=false;
                var error_field=false;
                for(var i in fields[inputid]) {
                  if(check[i] && (error_result=check[i](fields[inputid][i]))) {
                    error_field=i;
                    break;
                  }
                }
                if(error_result!='stop') {
                  if(error_result)
                    formbox_error(fields[inputid][error_field], error_result);
                  else
                    formbox_ok();
                }
              }
            });
          }
        });
      }
      $(document).ready(function() {
        _formbox_setup();
      });
    }
  });
}


//############################################################################
//# Please wait on form submit

function please_wait() {
  if($('#please-wait').length) {
    window.setTimeout(function() {
      if(typeof document.body.style.maxHeight==="undefined") { //IE6
        $('body','html').css({height: '100%', width: '100%'});
        $('html').css('overflow', 'hidden');
        $('body').append('<iframe id="blackout-iefix"></iframe>');
      }
      $('body').append('<div id="blackout-mask"></div>');
      $('#please-wait').css({display: 'block'});
    }, 1500);
  }
  return true;
}


//############################################################################
//# Contest voting

function vote_setup(url, id, vote) {
  (function($) {
    function _vote_show(newvote) {
      for(var n=1; n<=5; n++) {
        $('#vote-'+id+'-'+n).each(function() {
          var anchor=$(this);
          anchor.find('img').each(function() {
            $(this).attr('src', '/pix/icons/star_'+(n<=newvote ? 'full' : 'none')+'.gif');
          });
        });
      }
    }
    function _vote_save(newvote) {
      $.ajax({
        type: 'POST',
        url: url,
        data: 'submissionID='+encodeURIComponent(id)+'&vote='+encodeURIComponent(newvote),
        success: function(msg) {
          vote=newvote;
          _vote_show(vote);
        }
      });
    }
    function _vote_setup() {
      _vote_show(vote);
      for(var n=1; n<=5; n++) {
        $('#vote-'+id+'-'+n).each(function() {
          var hovervote=n;
          var anchor=$(this);
          anchor.mouseover(function() {
            _vote_show(hovervote);
          });
          anchor.mouseout(function() {
            _vote_show(vote);
          });
          anchor.click(function() {
            _vote_save(hovervote);
            return false;
          });
        });
      }
    }
    $(document).ready(function() {
      _vote_setup();
    });
  })(jQuery);
}


//############################################################################
//# Hide emails from spambots

function display_email(domain, user, link) {
  if(link)
    document.write('<a href="mailto:'+user+'@'+domain+(link==true ? '' : '?subject='+encodeURIComponent(link))+'">');
  document.write(user+'@'+domain);
  if(link)
    document.write('</a>');
}


//############################################################################
//# Currency selector

function setup_currency_links(html) {
  $(document).ready(function() {
    $('body').append(html);
    var currency_off=function() {
      $(document).unbind('click', currency_off);
      $('#currency-selector').hide();
      return true;
    };
    $('.currency-link').click(function(e) {
      if($('#currency-selector').is(':visible'))
        currency_off();
      else {
        $('#currency-selector').css({left: (e.pageX-5)+'px', top: (e.pageY-5)+'px'});
        $('#currency-selector').fadeIn('fast');
        $(document).bind('click', currency_off);
      }
      return false;
    });
  });
}


//############################################################################
//# Page setup

$(document).ready(function() {
  toggle_blocks();
  var language_off=function() {
    $(document).unbind('click', language_off);
    $('#language-list').hide();
    return true;
  };
  var language_on=function() {
    $('#language-list').fadeIn('fast');
    $(document).bind('click', language_off);
    return false;
  };
  $('#language-list-toggle').each(function() {
    var toggle=$(this);
    toggle.bind('click', function() {
      if($('#language-list').is(':visible'))
        language_off();
      else
        language_on();
      return false;
    });
  });
});

