String.prototype.lTrim = function() { return this.replace(/^\s*/, ""); };
String.prototype.rTrim = function() { return this.replace(/\s*$/, ""); };
String.prototype.trim = function() { return this.lTrim().rTrim(); };

RegExp.escape = function(text) {
  if (!arguments.callee.sRE) {
    var specials = [
      '/', '.', '*', '+', '?', '|',
      '(', ')', '[', ']', '{', '}', '\\'
    ];
    arguments.callee.sRE = new RegExp(
      '(\\' + specials.join('|\\') + ')', 'g'
    );
  }
  return text.replace(arguments.callee.sRE, '\\$1');
};

function getViewport() {
  var x, y;
  if (self.innerHeight) {
    y = self.innerHeight;
    x = self.innerWidth;
  }
  else if (document.documentElement && document.documentElement.clientHeight) {
    y = document.documentElement.clientHeight;
    x = document.documentElement.clientWidth;
  }
  else if (document.body) {
    y = document.body.clientHeight;
    x = document.body.clientWidth;
  }
  
  return [x,y];
}

if(typeof Lijit=="undefined"){
  var Lijit={staticBase: '', releaseTag : ''};
}

Lijit.init = function(e) {
  Lijit.LoginBox.init();
};

Lijit.register = function() {
  Event.observe(window, 'load', Lijit.init);
};

Lijit.res = function(url, rev, base) {
  if (base == null) {
    base = Lijit.staticBase;
  }
  if (base == null) {
    base = "";
  }
  if (rev == null) {
    rev = Lijit.releaseTag;
  }
  if (base.indexOf('http:') == 0 && document.location.protocol == 'https:') {
    // Adjust link to be SSL.
    base = 'https' + base.substring(4);
  }

  if (rev != null) {
    if (url.indexOf('/res/') == 0) {
      url = '/___' + rev + url;
    }
    else if (url.indexOf('/files/informers/') == 0) {
      url = '/files/informers/___' + rev + url.substring(17);
    }
  }

  return base + url;
};

Lijit.register();

/**
 * Get an the "real position" of an element.
 * Based on http://www.quirksmode.org/js/findpos.html
 * @arguments (dom)element
 */
Lijit.getElementPosition = function(el) {
	var curleft = curtop = 0;
	if (el.offsetParent) {	
		do {			
			curleft += el.offsetLeft;			
			curtop += el.offsetTop;	
		} while (el = el.offsetParent);
	}
	return [curleft,curtop];
}

Lijit.UserAutoComplete = {
  init:function() {
    var input = $('lijit_quick_user_search');
    if(input) {
      input.value = "";
      var userAutocompleter = 
        new Ajax.Autocompleter('lijit_quick_user_search', 
          'lijit_quick_user_search_auto_complete', 
          '/api/informers', 
          { minChars: 1, 
            updateElement: Lijit.UserAutoComplete.userSelected,
            indicator: 'lijit_quick_user_search_indicator'
          }
        );

      Event.observe('lijit_quick_search_form', 'submit', Lijit.UserAutoComplete.submit);
      Event.observe('find_a_user_link', 'click', Lijit.UserAutoComplete.toggle);
    }
  },
  submit:function(e) {
    // Don't allow submits, do the auto complete thing
    Event.stop(e);
  },
  firstFocus: true,
  focus:function(e) {
    // Make the searchbox bigger
    var input = $('lijit_quick_user_search');
    if(Lijit.UserAutoComplete.firstFocus) {
      new Effect.Scale(input, 200, {scaleContent: false, scaleY: false});
      Lijit.UserAutoComplete.firstFocus = false;
    }
    
  },
  userSelected:function (li){
    document.location.href = li.id;   
  },
  toggle:function(e) {
    var find_div = $('find_a_user_div');
    if(find_div) {
      if(find_div.visible())
          Effect.Fade(find_div, {duration: .5});
      else
        new Effect.Appear(find_div, {duration: .5, afterFinish: function(e){$('lijit_quick_user_search').focus();}});
    }
    Event.stop(e);
  }
};

/*
 * This script attatches a click event to the sign in button
 */
Lijit.LoginBox = {
	cookies: -1,
	init:function(e) {
		var signin_link = $('signin_link');
		if(signin_link) {
			Event.observe(signin_link, 'click', Lijit.LoginBox.toggle);
		}
	},
	toggle:function(pEvent) {
		// If the login box exists, stop the event, otherwise it will continue to the login page
		Event.stop(pEvent);
		var login_box = $('login');
		if(!login_box.visible()) {
			$J(login_box).fadeIn();
			$('username').focus();
			$('signin_link').addClassName('selected');
		} else {
			$J(login_box).fadeOut();
			$('signin_link').removeClassName('selected');
		}
	}
};

Lijit.ImageLoad = Class.create();

Lijit.ImageLoad.prototype = {
  image: null,
  initialize:function(img, target) {
    this.options = Object.extend({
      defaultImage: Lijit.res('/res/images/default_informer_image.png'),
      width: 16,
      height: 16,
      completeCheck: false
    }, arguments[2] || {});
    this.setup(img, target);    
  },
  setup:function(url, target) {
    this.target = $(target);
    if(!this.target || this.target.tagName != 'IMG')
      return;    // First set it to the default
    
    if(!this.target.src || this.target.src == '')
      this.reset();

    if (url && url != '') {
      this.image = new Image(this.options.width, this.options.height);
      if(navigator.appVersion.match(/Konqueror|Safari|KHTML/)) {
        this.image.onload = this.onLoad.bindAsEventListener(this);
        this.image.onerror = this.onError.bindAsEventListener(this);
      }
      else {
        Event.observe(this.image, 'load', this.onLoad.bindAsEventListener(this));
        Event.observe(this.image, 'error', this.onError.bindAsEventListener(this));
      }
      this.image.src = url;
    }
  },
  reset:function() {
    this.target.src = this.options.defaultImage;
  },
  onLoad:function(e) {
    // on a successful load, swap the image
    this.target.src = this.image.src;
  },
  onError:function(e) {
    // do nothing here
    this.favicon = null;
  }
};

Lijit.Favicon = Class.create();

Object.extend(Object.extend(Lijit.Favicon.prototype, Lijit.ImageLoad.prototype), {
  initialize:function(url, target) {
    this.options = Object.extend({
      defaultImage: Lijit.res('/res/images/default_favicon.png'),
      width: 16,
      height: 16,
      completeCheck: true
    }, arguments[2] || {});

    if (url && url != ''){
      if(url.startsWith('http://www.lijit.com/users/')) {
        this.setup('/informer_image.php?informer_uri=' + escape(url), target);
      }
      else {
        var parsedUrl = new Poly9.URLParser(url);
        this.setup('http://' + parsedUrl.getHost() + '/favicon.ico', target);
      }
    }
    else {
      this.setup('', target);
    }
  }
});

Lijit.Utils = {
   pause: function(ms) {
      var now=new Date();
      var exitTime=now.getTime()+ms;
      while(true){
        now=new Date();
        if (now.getTime() > exitTime) return;
      }
    },
    forceImgCallback: function(url) {
      var img = document.createElement('IMG');
      img.src = url;
      Lijit.Utils.pause(800);
    },
    linkTargetForEvent: function(e) {
      var target = null;
      if (e) {
          target = e.target;
      }
      else {
          target = window.event.srcElement;
      }
      target = Lijit.Utils.resolveTarget(target);
      if (target && target.nodeName.toUpperCase() == 'A') {
        var href = target.href;
        var linktext = null;
        if (target.innerHTML) {
          linktext = target.innerHTML;
        }
        else if (target.innerText) {
          linktext = target.innerText;
        }
        else if (target.text) {
          linktext = target.text;
        }
        if (target && linktext) {
          return { node: target, url: href, text: linktext };
        }
    }
    return null;
  },
  resolveTarget: function(obj) {
    for (var j=0; j<=5; j++) {
      if (obj && obj.nodeName.toUpperCase() == 'A') {
        return obj;
      }
      if (!obj.parentNode) {
        return null;
      }
      obj=obj.parentNode;
    }
    return null;
  },
  /**
   * Bolds Query result
   * @param {String} str Value to return, performs search on this string. Probably 'description' text.
   * @param {Regex} reg Regular expression for search.
   * @returns str properly bolded.
   */
  boldQuery:function(q, str) {
    if (!q || q.length == 0) {
      // No bolding to be done.
      return str;
    }
    // Delete boolean control characters (like plus and minus).
    var clean_q = q.replace(/[\+\-]/g, '');

    // Turn the query into an RE alternation; ensure matching on word boundary.
    var parts = $w(RegExp.escape(clean_q)).map(function (e) { return '\\b' + e +'\\b'; });
    var re = new RegExp("(" + parts.join("|") + ")", "gi");

    return str.replace(re,"<b>$1</b>"); 
  }
};

Lijit.Search = Class.create();

Lijit.Search = {
  BLOG: "blog",
  CONTENT: "content",
  NETWORK: "network",
  PICKS: "picks",
  recordResults:function(id, length) {
    // record results count
    if (length >= 0 && id && typeof(id) != 'undefined') {
      var params = 'id=' + id + '&count=' + length;
      var markReq = new Ajax.Request('/search_mark_count.html', { method: 'get', parameters: params });
    }
  }
};

/** 
* @projectDescription   Poly9's polyvalent URLParser class
*
* @author Denis Laprise - denis@poly9.com - http://poly9.com
* @version  0.1 
* @namespace  Poly9
*
* Usage: var p = new Poly9.URLParser('http://user:password@poly9.com/pathname?arguments=1#fragment');
* p.getHost() == 'poly9.com';
* p.getProtocol() == 'http';
* p.getPathname() == '/pathname';
* p.getQuerystring() == 'arguments=1';
* p.getFragment() == 'fragment';
* p.getUsername() == 'user';
* p.getPassword() == 'password';
*
* See the unit test file for more examples.
* URLParser is freely distributable under the terms of an MIT-style license.
*/

if (typeof Poly9 == 'undefined') {
 var Poly9 = {};
}

/**
 * Creates an URLParser instance
 *
 * @classDescription  Creates an URLParser instance
 * @return {Object} return an URLParser object
 * @param {String} url  The url to parse
 * @constructor
 * @exception {String}  Throws an exception if the specified url is invalid
 */
Poly9.URLParser = function(url) {
 this._fields = {'Username' : 4, 'Password' : 5, 'Port' : 7, 'Protocol' : 2, 'Host' : 6, 'Pathname' : 8, 'URL' : 0, 'Querystring' : 9, 'Fragment' : 10};
 this._values = {};
 this._regex = null;
 this.version = 0.1;
 this._regex = /^((\w+):\/\/)?((\w+):?(\w+)?@)?([^\/\?:]+):?(\d+)?(\/?[^\?#]+)?\??([^#]+)?#?(\w*)/;
 for(var f in this._fields)
  this['get' + f] = this._makeGetter(f);
 if (typeof url != 'undefined')
  this._parse(url);
};
 
/**
 * @method 
 * @param {String} url  The url to parse
 * @exception {String}  Throws an exception if the specified url is invalid
 */
Poly9.URLParser.prototype.setURL = function(url) {
  this._parse(url);
};

Poly9.URLParser.prototype._initValues = function() {
   for(var f in this._fields)
   this._values[f] = '';
};

Poly9.URLParser.prototype._parse = function(url) {
  this._initValues();
  var r = this._regex.exec(url);
  if (!r) throw "DPURLParser::_parse -> Invalid URL"
  for(var f in this._fields) if (typeof r[this._fields[f]] != 'undefined')
   this._values[f] = r[this._fields[f]];
};

Poly9.URLParser.prototype._makeGetter = function(field) {
 return function() {
  return this._values[field];
 }
};

Lijit.Tabs = Class.create();

Lijit.Tabs.prototype = {
  initialize:function(ul) {
    try{
      this.options = Object.extend({
        sortable: false,
        lockable: false,
        prefix: 'tab_',
        onSortComplete: function(){},
        onLockClick: function(){},
        onActivate: function(){},
        beforeActivate: function(){return true;}
      }, arguments[1] || {});
    
      this.ul = $(ul);
      
      if(this.options.sortable) {
        if(this.options.lockable) {
          this.lock = document.createElement('img');
          this.locked = false;
          this.lock.src = Lijit.res("/res/images/lock_unlocked.png");
          this.ul.appendChild(this.lock);
          this.lock.align = "right";
          Event.observe(this.lock, 'click', this.lockClick.bindAsEventListener(this));
          this.lockClick(null);
        }
        else {
          this.sortOn();
        }
      }
      
      var firstTab = location.hash;
      if(typeof firstTab == "undefined" || firstTab == "" || !$('stats_' + firstTab.substring(2))) {
        firstTab = this.ul.childElements().detect(function(li) {return (li.tagName.toUpperCase() == 'LI');}).id;
      }
      else {
        firstTab = firstTab.substring(2);
      }
      
      this.ul.childElements().each(function(li) {
        if(li.tagName.toUpperCase() == 'LI' && !li.hasClassName('ignore')) {
          Event.observe(li, 'click', this.tabClicked.bindAsEventListener(this));
        }
      }.bind(this));
      
      this.activateTab(firstTab);
    }
    catch(e) {
      //alert(e.message);
    }
  },
  tabClicked:function(e) {
    var target = $(Event.element(e));
    if (!this.options.beforeActivate(target)) {
      if (e) {
        Event.stop(e);
      }
      return false;
    }
    target.blur();
    while(!target.tagName || target.tagName.toUpperCase() != 'LI')
      target = $(target.parentNode);
    this.activateTab(target, e);
  },
  activateTab:function(target, e) {
    this.ul.childElements().each(function(li) {
      if(li.tagName.toUpperCase() == 'LI') {
        $(li).addClassName('inactive_button');
        $(li).removeClassName('active_button');
      }
    });
    
    $(target).addClassName('active_button');
    $(target).removeClassName('inactive_button');
    
    this.currentTab = $(target);
    this.options.onActivate($(target));
  },
  addTab:function(title) {
    var name = title.toLowerCase().replace(/ /gi, "_"); 
    var tab = $(document.createElement('li'));
    tab.id = "tab_" + name;
    tab.addClassName("inactive_button");
    
    var a = $(document.createElement('a'));
    a.id = tab.id + "_link";
    a.href = "#h" + tab.id;
    a.innerHTML = title;
    
    tab.appendChild(a);
    
    this.ul.appendChild(tab);
    Event.observe(tab, 'click', this.tabClicked.bindAsEventListener(this));
    if(this.options.sortable)
      this.sortOn();
    return tab;
  },
  removeTab:function(id) {
    var tab = $(id);
    if(tab)
      Element.remove(tab);
    if(this.options.sortable)
      this.sortOn();
    
    this.activateTab(this.getFirstTab());
  },
  getFirstTab:function() {
    return this.ul.childElements().detect(function(li) {return (li.tagName.toUpperCase() == 'LI');});
  },
  onSortComplete:function(ul) {
    this.options.onSortComplete();
  },
  lockClick:function(e) {
    this.locked = !this.locked;
    if(this.locked) {
      this.sortOff();
      this.lock.src = "/res/images/lock_locked.png";
      this.lock.title = "Make the tabs sortable";
    }
    else {
      this.sortOn();
      this.lock.src = "/res/images/lock_unlocked.png";
      this.lock.title = "Make the tabs un-sortable";
    }
    
    this.options.onLockClick(this.locked);
  },
  sortOn:function() {
    Sortable.create(this.ul, {tag: 'li', ghosting: false, constraint: 'horizontal', overlap: 'horizontal', onUpdate: this.onSortComplete.bindAsEventListener(this)});
  },
  sortOff:function() {
    Sortable.destroy(this.ul);
  }
};

Lijit.SwitchableDivs = Class.create();

Lijit.SwitchableDivs.prototype = {
	initialize:function() {
		this.options = Object.extend({
			sortable: false,
			onSortComplete: {},
			beforeActivate: function(){return true;}
		}, arguments[0] || {});	
		
		this.divs = [];
	},
	addDiv:function(clickable, target, onActivate) {
		this.divs.push({clickable: $(clickable), target: $(target), onActivate: onActivate});
		Event.observe($(clickable), 'click', (function(e) { this.activateDiv($(clickable), e) }).bindAsEventListener(this));
	},
	removeDiv:function(clickable, target) {
		this.divs = this.divs.select(function(div) {
			return !(div.clickable == clickable && div.target == target);
		});
	},
	activateDiv:function(clickable, e) {
		clickable = $(clickable);
		if (!this.options.beforeActivate(clickable)) {
			if (e) {
				Event.stop(e);
			}
			return false;
		}
		// turn off all divs
		this.divs.each(function(div) {
			try{
				$(div.target).hide();
				if (div.clickable == clickable) {
					$(div.target).show();
				}
				if (div.onActivate) {
					div.onActivate();
				}
			} catch(e){}
		});
		
	}
};


/**
 *
 * @params string The ID of the form
 * @params string The Url we are calling
 * @params function callback on succes
 */
Lijit.PrimaryUrlChecker = function(form_el, url, callback) {
    var form_el = $(form_el);
    var message = form_el.getElementsByClassName('set_primary_status')[0];

    function isSuccess( resp ) {
        // Loop through form's child elements and hide them.
        var childEls = form_el.childElements().without( message );
        childEls.each(Element.hide);
        message.innerHTML = "Thanks for entering your primary URL! You can change it in the future from the Manage Search link above.";
        message.show();
        // Hide other instances of form on page, if they are around. Get all the
        // other elements with enterPrimaryUrl class besides the "this" one,
        // and hide them.
        var otherFormEls = [];
        var formEls = $$('.set_primary');
        formEls.each( function(el) {
            if (el.id !== form_el.id) {
                var theParent = el.ancestors()[0];
                otherFormEls.push(theParent);
            }
        });
        otherFormEls.each(Element.hide);
    }
    function isFail( resp ) {
        message.innerHTML = resp.reason || "We are unable set your primary url. Please try again later";
        message.show();
    }

    Event.observe( form_el, 'submit', function(e) {
        var inp = form_el.getElementsByClassName('set_primay_blog')[0];
        if (inp.value.strip()) {
            new Ajax.Request(url + encodeURIComponent(inp.value), {
                method: 'get',
                onFailure: function(resp) {
                    var resp = resp.responseJSON;
                    isFail( resp );
                },
                onSuccess: function(resp) {
                    var resp = resp.responseJSON;
                    if ( resp.success ) {
                        if (callback) {
                            callback( resp );
                        }
                        else {
                            isSuccess( resp );
                        }
                    }
                    else {
                        isFail( resp );
                    }
                }
            });
        }
        else {
            isFail( {'reason':"Please enter a URL."} );
        }

        Event.stop( e );
    });
};

