var Femtoverlay;
var Pager
(function() {
  // Femtoverlay: a barebones lightbox-like implementation with self-contained CSS
  Femtoverlay=new Class({
		Implements:[Events,Options],
		options:{
			onOpen:$empty,
			onClose:$empty,
			onCreate:$empty,
			onDestroy:$empty,
			closable:true,
			size:{x:600,y:400},
			element:null,
			zIndex:60000,
			overlayDisplay:null
		},
		initialize:function(a){
			this.setOptions(a);
			if(this.options.element){
        $$(this.options.element).addEvent("click",function(e){e.stop();this.open(e)}.bind(this));
			}
		},
		reposition:function(b,a){
			b=b||{};
			if(b.x){
				this.options.size.x=b.x;
			}
			if(b.y){
				this.options.size.y=b.y;
			}

			if(this.femtocontent){
				this.femtocontent[a?"morph":"setStyles"]({
					width:this.options.size.x,
					height:this.options.size.y,
					marginLeft:-(this.options.size.x)/2,
					marginTop:document.getScroll().y + ((this.options.size.y>document.getSize().y)?(-document.getSize().y/2):(-this.options.size.y/2))
				});
			}
			if($("femtoverlay"))
				$("femtoverlay").setStyle("height",document.getScrollSize().y);
		},
		open:function(event){
			if($("femtoverlay")){
				return;
			}
			var a=this,
			b=this.options;

			var events = null;
			if (this.options.closable){
				events = {
					click:this.close.bind(this)
				};
			}
			this.overlay=new Element("div",{
				id:"femtoverlay",
				events: events,
				tween:{
					duration:this.options.overlayDisplay?1:500,
					onComplete:function(){
						if(a.overlay.get("opacity")===0){
							a.fireEvent("close");
							a.overlay.dispose()
						}else{
							a.femtocontent=new Element("div",{id:"femtocontent",styles:{position:"absolute",top:"50%",left:"50%",overflow:"hidden",zIndex:b.zIndex+2}}).inject(document.body);
							a.reposition();
							a.isOpen=true;
							a.fireEvent("open",a.femtocontent)
						}
					}
				},
				styles:{
					position:"absolute",
					left:0,
					top:0,
					width:"100%",
					backgroundColor:"#000",
					opacity:0,
					zIndex:b.zIndex,
					display:a.options.overlayDisplay
				}
			}).inject(document.body).fade(0.6);
			this.reposition();
			if (this.options.closable){
				this.key_close_fn=function(c){
					if(c.key=="esc" && ($$(".tooltip_overlay").length === 0 || $$(".tooltip_overlay")[0].getStyle('display') == 'none')){
						c.stopPropagation();
						a.close();
					}
				};
				document.addEvent("keydown",this.key_close_fn);
			}
			window.addEvent("resize",this.reposition.bind(this));
			this.fireEvent("create", event);
		},
		close:function(){
			if(this.femtocontent){
				this.femtocontent.dispose();
			}
			this.isOpen=false;
			window.removeEvent("resize",this.reposition);
			document.removeEvent("keydown",this.key_close_fn);
			this.fireEvent("destroy");
			$("femtoverlay").fade("out");
		}
	});

  /* moopop: unobtrusive javascript popups via late binding using mootools 1.2 */
  /* copyright (c) 2007-2008 by gonchuki - http://blog.gonchuki.com */
  var moopop={width:0,height:0,captureByRel:function(attrVal,parent){this.capture((parent||document).getElements('a[rel*='+(attrVal||'popup')+']'));},capture:function(el,width,height){if($defined(width)&&$defined(height)){this.width=width;this.height=height;}
  switch($type(el)){case'string':el=$$(el);case'element':case'array':$splat(el).each(this.add_pop_to,this);}
  this.width=null;this.height=null;},add_pop_to:function(el){el.addEvent('click',function(e){e.stop();this.popup(el);}.bind(this));var size=el.get('rel').match(/\[(\d+),\s*(\d+)/)||['',this.width,this.height];var resizable=el.get('rel').match(/,(r)/)||[];if(size[1])el.store('popupprops','width='+size[1]+', height='+size[2]+(resizable[1]?', scrollbars=yes, resizable=yes':''));},popup:function(el){window.open(el.get('href'),el.get('name')||'',el.retrieve('popupprops')||'');}};

  /* tooltip class from mootools-more */
  //MooTools More, <http://mootools.net/more>. Copyright (c) 2006-2009 Aaron Newton <http://clientcide.com/>, Valerio Proietti <http://mad4milk.net> & the MooTools team <http://mootools.net/developers>, MIT Style License.
  MooTools.More={version:"1.2.4.2"};

	var Tips=new Class({
		Implements:[Events,Options],
		options:{
			onShow:function(a){a.setStyle("visibility","visible");},
			onHide:function(a){a.setStyle("visibility","hidden");},
			title:"title",
			text:function(a){return a.get("rel")||a.get("href");},
			showDelay:100,
			hideDelay:100,
			className:null,
			offset:{x:16,y:16},
			fixed:false
		},
		initialize:function(){
			var a=Array.link(arguments,{options:Object.type,elements:$defined});
  		if(a.options&&a.options.offsets){
				a.options.offset=a.options.offsets;
			}
			this.setOptions(a.options);
			this.container=new Element("div",{"class":"tip"});
			this.tip=this.getTip();
  		if(a.elements){this.attach(a.elements);}
		},
		getTip:function(){
			return new Element("div",{"class":this.options.className,styles:{visibility:"hidden",display:"none",position:"absolute",top:0,left:0}}).adopt(new Element("div",{"class":"tip-top"}),this.container,new Element("div",{"class":"tip-bottom"})).inject(document.body);
  	},
		attach:function(b){
			var a=function(d,c){if(d==null){return"";}return $type(d)=="function"?d(c):c.get(d);};$$(b).each(function(d){var e=a(this.options.title,d);
  d.erase("title").store("tip:native",e).retrieve("tip:title",e);d.retrieve("tip:text",a(this.options.text,d));var c=["enter","leave"];if(!this.options.fixed){c.push("move");
  }c.each(function(f){d.addEvent("mouse"+f,d.retrieve("tip:"+f,this["element"+f.capitalize()].bindWithEvent(this,d)));},this);},this);
			return this;
		},
		detach:function(a){
			$$(a).each(function(c){["enter","leave","move"].each(function(d){c.removeEvent("mouse"+d,c.retrieve("tip:"+d)||$empty);
  		});c.eliminate("tip:enter").eliminate("tip:leave").eliminate("tip:move");if($type(this.options.title)=="string"&&this.options.title=="title"){var b=c.retrieve("tip:native");
  		if(b){c.set("title",b);}}},this);return this;
		},
		elementEnter:function(b,a){
			$A(this.container.childNodes).each(Element.dispose);["title","text"].each(function(d){var c=a.retrieve("tip:"+d);
  		if(!c){return;}this[d+"Element"]=new Element("div",{"class":"tip-"+d}).inject(this.container);this.fill(this[d+"Element"],c);},this);this.timer=$clear(this.timer);
  		this.timer=this.show.delay(this.options.showDelay,this,a);this.tip.setStyle("display","block");this.position((!this.options.fixed)?b:{page:a.getPosition()});
  	},
		elementLeave:function(b,a){
			$clear(this.timer);
			this.tip.setStyle("display","none");
			this.timer=this.hide.delay(this.options.hideDelay,this,a);
		},
		elementMove:function(a){
			this.position(a);
  	},
		position:function(d){
			var b=window.getSize(),a=window.getScroll(),e={x:this.tip.offsetWidth,y:this.tip.offsetHeight},c={x:"left",y:"top"},f={};
			for(var g in c){
				f[c[g]]=d.page[g]+this.options.offset[g];
  			if((f[c[g]]+e[g]-a[g])>b[g]){
					f[c[g]]=d.page[g]-this.options.offset[g]-e[g];
				}
			}
			this.tip.setStyles(f);
		},
		fill:function(a,b){
			if(typeof b=="string"){
				a.set("html",b);
  			}else{
					a.adopt(b);
				}
		},
		show:function(a){
			this.fireEvent("show",[this.tip,a]);
		},
		hide:function(a){
			this.fireEvent("hide",[this.tip,a]);
		}
	});

	Element.implement({
	  toJSON: function() {
	    var json = {};
	    this.getElements('input, select, textarea', true).each(function(el){
	      if (!el.name || el.disabled || el.type == 'submit' || el.type == 'reset' || el.type == 'file') return;
	      var value = (el.tagName.toLowerCase() == 'select') ? Element.getSelected(el).map(function(opt){
	        return opt.value;
	      }) : ((el.type == 'radio' || el.type == 'checkbox') && !el.checked) ? null : el.value;
	      $splat(value).each(function(val){
	        if (typeof val != 'undefined') json[el.name] = val;
	      });
	    });
			return json;
	    //return JSON.encode(json);
	  }
	});

  var intcomma = function(value, is_decimal) {
    if (!value){
      if (typeof value == "number" && is_decimal){
        return '0.00';
      }
      return value;
    }
    // Now with added decimal places! (only if included)
    var matches = /^(-?)(\d+)(?:(?:\.)(\d+))?$/.exec(value.toString());
    if (matches) {
      var neg = matches[1];
      var dollars = matches[2];
      var cents = matches[3] ? matches[3] : (is_decimal ? '00' : '');
      if (cents.length) {
        cents = '.' + cents + '00';
        cents = cents.substr(0, 3);
      }
      var commaDollars = '';
      while (dollars.length > 3) {
        commaDollars = dollars.substr(dollars.length - 3) + ',' + commaDollars;
        dollars = dollars.substr(0, dollars.length - 3);
      }
      if (dollars.length) {
        commaDollars = dollars + ',' + commaDollars;
      }
      commaDollars = commaDollars.substr(0, commaDollars.length - 1);
      return neg + commaDollars + cents;
    }
    return value.toString();
  };

  var dwDefaults = new Class({
      //implements
      Implements: [Options],

      //options
      options: {
        collection: jq('input[type=text]')
      },

      //initialization
      initialize: function(options) {
        //set options
        this.setOptions(options);
        this.defaults();
      },

      //a method that does whatever you want
      defaults: function() {
        jq.each(this.options.collection, function(index, el){
          el = jq(el)
          el.val(el.attr('rel'));
          el.focus(function() {
              if(el.val() == el.attr('rel')) {
                el.val('');
                el.removeClass('def');
              }
          });
          el.blur(function() {
            if(el.val() == ''){
              el.val(el.attr('rel'));
              el.addClass('def');
            }
          });
        });
      }

  });

var Drag=new Class({Implements:[Events,Options],options:{snap:6,unit:"px",grid:false,style:true,limit:false,handle:false,invert:false,preventDefault:false,stopPropagation:false,modifiers:{x:"left",y:"top"}},initialize:function(){var b=Array.link(arguments,{options:Object.type,element:$defined});
this.element=document.id(b.element);this.document=this.element.getDocument();this.setOptions(b.options||{});var a=$type(this.options.handle);this.handles=((a=="array"||a=="collection")?$$(this.options.handle):document.id(this.options.handle))||this.element;
this.mouse={now:{},pos:{}};this.value={start:{},now:{}};this.selection=(Browser.Engine.trident)?"selectstart":"mousedown";this.bound={start:this.start.bind(this),check:this.check.bind(this),drag:this.drag.bind(this),stop:this.stop.bind(this),cancel:this.cancel.bind(this),eventStop:$lambda(false)};
this.attach();},attach:function(){this.handles.addEvent("mousedown",this.bound.start);return this;},detach:function(){this.handles.removeEvent("mousedown",this.bound.start);
return this;},start:function(c){if(c.rightClick){return;}if(this.options.preventDefault){c.preventDefault();}if(this.options.stopPropagation){c.stopPropagation();
}this.mouse.start=c.page;this.fireEvent("beforeStart",this.element);var a=this.options.limit;this.limit={x:[],y:[]};for(var d in this.options.modifiers){if(!this.options.modifiers[d]){continue;
}if(this.options.style){this.value.now[d]=this.element.getStyle(this.options.modifiers[d]).toInt();}else{this.value.now[d]=this.element[this.options.modifiers[d]];
}if(this.options.invert){this.value.now[d]*=-1;}this.mouse.pos[d]=c.page[d]-this.value.now[d];if(a&&a[d]){for(var b=2;b--;b){if($chk(a[d][b])){this.limit[d][b]=$lambda(a[d][b])();
}}}}if($type(this.options.grid)=="number"){this.options.grid={x:this.options.grid,y:this.options.grid};}this.document.addEvents({mousemove:this.bound.check,mouseup:this.bound.cancel});
this.document.addEvent(this.selection,this.bound.eventStop);},check:function(a){if(this.options.preventDefault){a.preventDefault();}var b=Math.round(Math.sqrt(Math.pow(a.page.x-this.mouse.start.x,2)+Math.pow(a.page.y-this.mouse.start.y,2)));
if(b>this.options.snap){this.cancel();this.document.addEvents({mousemove:this.bound.drag,mouseup:this.bound.stop});this.fireEvent("start",[this.element,a]).fireEvent("snap",this.element);
}},drag:function(a){if(this.options.preventDefault){a.preventDefault();}this.mouse.now=a.page;for(var b in this.options.modifiers){if(!this.options.modifiers[b]){continue;
}this.value.now[b]=this.mouse.now[b]-this.mouse.pos[b];if(this.options.invert){this.value.now[b]*=-1;}if(this.options.limit&&this.limit[b]){if($chk(this.limit[b][1])&&(this.value.now[b]>this.limit[b][1])){this.value.now[b]=this.limit[b][1];
}else{if($chk(this.limit[b][0])&&(this.value.now[b]<this.limit[b][0])){this.value.now[b]=this.limit[b][0];}}}if(this.options.grid[b]){this.value.now[b]-=((this.value.now[b]-(this.limit[b][0]||0))%this.options.grid[b]);
}if(this.options.style){this.element.setStyle(this.options.modifiers[b],this.value.now[b]+this.options.unit);}else{this.element[this.options.modifiers[b]]=this.value.now[b];
}}this.fireEvent("drag",[this.element,a]);},cancel:function(a){this.document.removeEvent("mousemove",this.bound.check);this.document.removeEvent("mouseup",this.bound.cancel);
if(a){this.document.removeEvent(this.selection,this.bound.eventStop);this.fireEvent("cancel",this.element);}},stop:function(a){this.document.removeEvent(this.selection,this.bound.eventStop);
this.document.removeEvent("mousemove",this.bound.drag);this.document.removeEvent("mouseup",this.bound.stop);if(a){this.fireEvent("complete",[this.element,a]);
}}});Element.implement({makeResizable:function(a){var b=new Drag(this,$merge({modifiers:{x:"width",y:"height"}},a));this.store("resizer",b);return b.addEvent("drag",function(){this.fireEvent("resize",b);
}.bind(this));}});Drag.Move=new Class({Extends:Drag,options:{droppables:[],container:false,precalculate:false,includeMargins:true,checkDroppables:true},initialize:function(b,a){this.parent(b,a);
b=this.element;this.droppables=$$(this.options.droppables);this.container=document.id(this.options.container);if(this.container&&$type(this.container)!="element"){this.container=document.id(this.container.getDocument().body);
}var c=b.getStyles("left","top","position");if(c.left=="auto"||c.top=="auto"){b.setPosition(b.getPosition(b.getOffsetParent()));}if(c.position=="static"){b.setStyle("position","absolute");
}this.addEvent("start",this.checkDroppables,true);this.overed=null;},start:function(a){if(this.container){this.options.limit=this.calculateLimit();}if(this.options.precalculate){this.positions=this.droppables.map(function(b){return b.getCoordinates();
});}this.parent(a);},calculateLimit:function(){var d=this.element.getOffsetParent(),g=this.container.getCoordinates(d),f={},c={},b={},i={},k={};["top","right","bottom","left"].each(function(o){f[o]=this.container.getStyle("border-"+o).toInt();
b[o]=this.element.getStyle("border-"+o).toInt();c[o]=this.element.getStyle("margin-"+o).toInt();i[o]=this.container.getStyle("margin-"+o).toInt();k[o]=d.getStyle("padding-"+o).toInt();
},this);var e=this.element.offsetWidth+c.left+c.right,n=this.element.offsetHeight+c.top+c.bottom,h=0,j=0,m=g.right-f.right-e,a=g.bottom-f.bottom-n;if(this.options.includeMargins){h+=c.left;
j+=c.top;}else{m+=c.right;a+=c.bottom;}if(this.element.getStyle("position")=="relative"){var l=this.element.getCoordinates(d);l.left-=this.element.getStyle("left").toInt();
l.top-=this.element.getStyle("top").toInt();h+=f.left-l.left;j+=f.top-l.top;m+=c.left-l.left;a+=c.top-l.top;if(this.container!=d){h+=i.left+k.left;j+=(Browser.Engine.trident4?0:i.top)+k.top;
}}else{h-=c.left;j-=c.top;if(this.container==d){m-=f.left;a-=f.top;}else{h+=g.left+f.left;j+=g.top+f.top;}}return{x:[h,m],y:[j,a]};},checkAgainst:function(c,b){c=(this.positions)?this.positions[b]:c.getCoordinates();
var a=this.mouse.now;return(a.x>c.left&&a.x<c.right&&a.y<c.bottom&&a.y>c.top);},checkDroppables:function(){var a=this.droppables.filter(this.checkAgainst,this).getLast();
if(this.overed!=a){if(this.overed){this.fireEvent("leave",[this.element,this.overed]);}if(a){this.fireEvent("enter",[this.element,a]);}this.overed=a;}},drag:function(a){this.parent(a);
if(this.options.checkDroppables&&this.droppables.length){this.checkDroppables();}},stop:function(a){this.checkDroppables();this.fireEvent("drop",[this.element,this.overed,a]);
this.overed=null;return this.parent(a);}});Element.implement({makeDraggable:function(a){var b=new Drag.Move(this,a);this.store("dragger",b);return b;}});

/*
Class: Slider
        Creates a slider with two elements: a knob and a container. Returns the values.
Note:
        The Slider requires an XHTML doctype.
Arguments:
        element - the knob container
        knob - the handle
        options - see Options below
        maxknob - an optional maximum slider handle
Options:
		start - the minimum value for your slider.
		end - the maximum value for your slider.
        mode - either 'horizontal' or 'vertical'. defaults to horizontal.
        offset - relative offset for knob position. default to 0.
        knobheight - positions the max slider knob
		snap - whether the slider will slide in steps
		numsteps - number of slide steps
Events:
        onChange - a function to fire when the value changes.
        onComplete - a function to fire when you're done dragging.
        onTick - optionally, you can alter the onTick behavior, for example displaying an effect of the knob moving to the desired position.
                Passes as parameter the new position.
*/
var Slider = new Class({
	options: {
		onChange: Class.empty,
		onComplete: Class.empty,
		onTick: function(pos){
			this.moveKnob.setStyle(this.p, pos);
		},
		start: 0,
		end: 100,
		offset: 0,
		knobheight: 20,
		knobwidth: 14,
		mode: 'horizontal',
		clip_w:0,
		clip_l:0,
		isinit:true,
		snap: false,
		range: false,
		numsteps:null
	},
    initialize: function(el, knob,bkg, options, maxknob) {
		this.setOptions(options);
		this.element = $(el);
		this.knob = $(knob);
		this.previousChange = this.previousEnd = this.step = -1;
		this.bkg = $(bkg);
		if(this.options.steps==null){
			this.options.steps = this.options.end - this.options.start;
		}
		if(maxknob!=null)
			this.maxknob = $(maxknob);
		//else
		//	this.element.addEvent('mousedown', this.clickedElement.bindWithEvent(this));
		var mod, offset;
		switch(this.options.mode){
			case 'horizontal':
				this.z = 'x';
				this.p = 'left';
				mod = {'x': 'left', 'y': false};
				offset = 'offsetWidth';
				break;
			case 'vertical':
				this.z = 'y';
				this.p = 'top';
				mod = {'x': false, 'y': 'top'};
				offset = 'offsetHeight';
		}
		this.max = this.element[offset] - this.knob[offset] + (this.options.offset * 2);
		this.half = this.knob[offset]/2;
		this.full = this.element[offset] - this.knob[offset] + (this.options.offset * 2);
		this.min = $chk(this.options.range[0]) ? this.options.range[0] : 0;
		this.getPos = this.element['get' + this.p.capitalize()].bind(this.element);
		this.knob.setStyle('position', 'relative').setStyle(this.p, - this.options.offset);

		this.range = this.max - this.min;
		this.steps = this.options.steps || this.full;
		this.stepSize = Math.abs(this.range) / this.steps;
		this.stepWidth = this.stepSize * this.full / Math.abs(this.range) ;


		if(maxknob != null) {
			this.maxPreviousChange = -1;
			this.maxPreviousEnd = -1;
			this.maxstep = this.options.end;
			this.maxknob.setStyle('position', 'relative').setStyle(this.p, + this.max - this.options.offset).setStyle('bottom', this.options.knobheight);
		}
		var lim = {};
		//status = this.z
		lim[this.z] = [- this.options.offset, this.max - this.options.offset];
		//lim[this.z] = [100, this.max - this.options.offset];

		this.drag = new Drag(this.knob, {
			limit: lim,
			modifiers: mod,
			snap: 0,
			onStart: function(){
					this.draggedKnob();
			}.bind(this),
			onDrag: function(){
					this.draggedKnob();
			}.bind(this),
			onComplete: function(){
					this.draggedKnob();
					this.end();
			}.bind(this)
		});
		if(maxknob != null) {
			this.maxdrag = new Drag(this.maxknob, {
				limit: lim,
				modifiers: mod,
				snap: 0,
				onStart: function(){
					this.draggedKnob(1);
				}.bind(this),
				onDrag: function(){
					this.draggedKnob(1);
				}.bind(this),
				onComplete: function(){
					this.draggedKnob(1);
					this.end();
				}.bind(this)
			});
		}

		if (this.options.snap) {
			//this.drag.options.grid = Math.ceil(this.stepWidth);
			this.drag.options.grid = (this.full)/this.options.numsteps ;
			this.drag.options.limit[this.z][1] = this.full;
			//this.drag.options.grid = this.drag.options.grid - (this.knob[offset]/this.options.numsteps);
			status = "GRID - " + this.drag.options.grid  + "  , full = " + this.full// DEBUG

		}
		if (this.options.initialize) this.options.initialize.call(this);
    },
  getValues: function() {
		if(this.step < this.maxstep){
				return { minpos: this.step, maxpos: this.maxstep };
			}
			else{
				return { minpos: this.maxstep, maxpos: this.step };
			}
	},
	setMin: function(stepMin){
		this.step = stepMin.limit(this.options.start, this.options.end);
		this.checkStep();
		//this.end();
		this.moveKnob = this.knob;
		this.bkg.style.clip = "rect(0px "+  (parseInt(this.toPosition(this.step)) +3) + "px 10px 0px)";
		status =this.bkg.style.clip + "  vl= " + parseInt(this.toPosition(this.step)) ; //Debug
		this.fireEvent('onTick', this.toPosition(this.step));
		return this;
	},
	setMax: function(stepMax){
		this.maxstep = stepMax.limit(this.options.start, this.options.end);
		this.checkStep(1);
		//this.end();
		this.moveKnob = this.maxknob;
		var w= Math.abs(this.toPosition(this.step)- this.toPosition(this.maxstep)) + 3 ;
		var r = parseInt(this.clip_l + w);
		this.bkg.style.clip = "rect(0px "+  r + "px 10px "+ this.clip_l + "px)";

		this.fireEvent('onTick', this.toPosition(this.maxstep));
		// For Init Only
		if(this.options.isinit){
			var lim = {}; var mi,mx;
			mi = - this.options.offset;
			mx= parseInt(this.maxknob.getStyle('left')) - this.options.offset-4 ;
			lim[this.z] = [mi, mx];
			this.drag.options.limit = lim;
			this.options.isinit = false;
		}
		return this;
	},
	clickedElement: function(event){
		var position = event.page[this.z] - this.getPos() - this.half;
		position = position.limit(-this.options.offset, this.max -this.options.offset);

		this.step = this.toStep(position);

		//this.moveKnob = this.knob;
		this.bkg.style.clip = "rect(0px "+  (parseInt(this.toPosition(this.step)) +3) + "px 10px 0px)"
		//status =this.bkg.style.clip; //Debug
		this.checkStep();
		this.end();
		this.fireEvent('onTick', position);
	},

	draggedKnob: function(mx){
		var lim = {}; var mi,mx;
		if(mx==null) {
			this.step = this.toStep(this.drag.value.now[this.z]);
			this.checkStep();
		}else {
			this.maxstep = this.toStep(this.maxdrag.value.now[this.z]);
			this.checkStep(1);
		}
	},
	checkStep: function(mx){
		var lim = {}; var mi,mx;
		var limm = {};
		if(mx==null) {if (this.previousChange != this.step){this.previousChange = this.step;}}
		else {if (this.maxPreviousChange != this.maxstep){this.maxPreviousChange = this.maxstep;}}

		if(this.maxknob!=null) {

			mi = - this.options.offset;
			mx= parseInt(this.maxknob.getStyle('left')) - this.options.offset-4 ;
			//mx= parseInt(this.maxknob.getStyle('left')) - this.options.offset ;
			lim[this.z] = [mi, mx];
			this.drag.options.limit = lim;


			mi = parseInt(this.knob.getStyle('left'))-this.options.offset+22;
			//mi = parseInt(this.knob.getStyle('left'))-this.options.offset;

			mx= this.max - this.options.offset;
			limm[this.z] = [mi, mx];
			this.maxdrag.options.limit = limm;

			if(this.step < this.maxstep){
				this.fireEvent('onChange', { minpos: this.step, maxpos: this.maxstep });
				//this.clip_l = parseInt(this.knob.getStyle('left'));
			}
			else{
				this.fireEvent('onChange', { minpos: this.maxstep, maxpos: this.step });
				//this.clip_l = (parseInt(this.maxknob.getStyle('left')) + 10) ;
			}
			this.clip_l = parseInt(this.knob.getStyle('left')) + 10;
			//var w = Math.abs(parseInt(this.knob.getStyle('left')) - parseInt(this.maxknob.getStyle('left'))) + 3;
			var w = Math.abs(parseInt(this.knob.getStyle('left')) - parseInt(this.maxknob.getStyle('left')));
			//if(w > 3) w = w+3;

			var r = parseInt(this.clip_l + w);
			this.bkg.style.clip = "rect(0px "+  r + "px 10px "+ this.clip_l + "px)"
			//status =this.bkg.style.clip  + " w= " + w //Debug

		}else {
			this.fireEvent('onChange', this.step);
			this.bkg.style.clip = "rect(0px "+  (parseInt(this.drag.value.now[this.z]) +3)  + "px 10px 0px)"

		}
	},
	end: function(){
		if (this.previousEnd !== this.step || (this.maxknob != null && this.maxPreviousEnd != this.maxstep)) {
			this.previousEnd = this.step;
			if(this.maxknob != null) {
				this.maxPreviousEnd = this.maxstep;
				if(this.step < this.maxstep)
					this.fireEvent('onComplete', { minpos: this.step + '', maxpos: this.maxstep + '' });
				else
					this.fireEvent('onComplete', { minpos: this.maxstep + '', maxpos: this.step + '' });
			}else{
				this.fireEvent('onComplete', this.step + '');
			}
		}
	},

	toStep: function(position){
		return Math.round((position + this.options.offset) / this.max * this.options.steps) + this.options.start;
	},

	toPosition: function(step){
		return (this.max * step / this.options.steps) - (this.max * this.options.start / this.options.steps) - this.options.offset;
	}

});

Slider.implement(new Events);
Slider.implement(new Options);

	var PopupTips = new Class({
		Extends: Tips,
		overlay: null,
		options:{
			onShow:function(a){
				var self = this;
				if(!this.overlay) {
					this.overlay = new Element("div",
						{
							"class":this.options.className + '_overlay tooltip_overlay'
						}).inject(document.body).addEvent('click',function(){
							self.tip.setStyle("display","none");
							self.overlay.setStyle("display","none");
						});
				}
				a.setStyle("visibility","visible");
				self.overlay.setStyle("display","block").setStyle("height",document.getScrollSize().y);
			},
			onHide:function(a){a.setStyle("visibility","hidden");self.overlay.setStyle("display","none");},
			title:"title",
			text:function(a){return a.get("rel")||a.get("href");},
			showDelay:100,
			hideDelay:1000,
			className:null,
			offset:{x:16,y:16},
			fixed:false
		},
		attach:function(b){
			var a=function(d,c){
				if(d==null){return"";}
				return $type(d)=="function"?d(c):c.get(d);
			};
			$$(b).each(function(d){
				var e=a(this.options.title,d);
  			d.erase("title").store("tip:native",e).retrieve("tip:title",e);
				d.retrieve("tip:text",a(this.options.text,d));
				d.addEvent("click",d.retrieve("tip:enter",this["elementEnter"].bindWithEvent(this,d)));
			},this);
			return this;
		},
		getTip:function(){
			var self = this;
			var div = new Element("div",
				{
					"class":this.options.className,
					styles:{visibility:"hidden",display:"none",position:"absolute",top:0,left:0}
				}).adopt(new Element("div",{"class":"tip-top"}),new Element("a",{"class":"close",id:'popupClose'}),this.container,new Element("div",{"class":"tip-bottom"})).inject(document.body);

			$('popupClose').set('text','Close').addEvent('click',function(){
				self.tip.setStyle("display","none");
				self.overlay.setStyle("display","none");
			});
			return div;
		},
		position: function(event){
			var size = window.getSize(), scroll = window.getScroll(),
				tip = {x: this.tip.offsetWidth, y: this.tip.offsetHeight},
				props = {x: 'left', y: 'top'},
				obj = {};

			for (var z in props){
				obj[props[z]] = event.page[z] + this.options.offset[z];
				if ((obj[props[z]] + tip[z] - scroll[z]) > size[z]) obj[props[z]] = event.page[z] - this.options.offset[z] - tip[z];
			}

			obj.left = (document.getSize().x / 2) - (this.tip.getSize().x / 2) + 'px';

			this.tip.setStyles(obj);
		}
	});


	var Templates = {
		infoTemplate: '<div class="user_info">{pub_data}</div>',
    innerTemplate: '<dl class="info">{info}</dl>',
    templateChunks: {
      profile_image_url: '<img src="{profile_image_url}" alt="" class="thumbnail" />',
      display_name: '<h1>{display_name}</h1>',
      client_followers_count: '<p class="stats">{client_followers_count} Followers, {twitter_avg_tweets} Avg. Daily Tweets</p>',
      about_publisher: '<dt>About Publisher:</dt><dd>{about_publisher}</dd>',
      categories: '<dt>Categories:</dt><dd>{categories}</dd>',
      location: '<dt>Location:</dt><dd>{location}</dd>',
      client_screen_name: '<dt>Profile Page:</dt><dd><a href="{profile_url}" target="_blank">{profile_url}</a></dd>',
      add_user: ''
    }
	};
  var SponsorLab = {
    init: function() {
      this.rounded_boxes();
      this.activate_dependables();
      this.activate_collapsibles();
      this.activate_campaign_moreinfo();
      this.activate_autoclear_fields(document.getElements('input.autoclear, #header_controls input.text'));
      this.set_up_campaign();
      this.hook_settings();
      this.hook_signup();
      this.hook_payout_options();
      this.hook_single_submit();
      this.check_payment_methods();
      this.activate_payment_cards();
      this.activate_message_previews();
      this.activate_sample_bitly_urls();
      this.hook_table_cells();
      this.activate_coming_soon_urls();
      this.hook_publisher_change_response();
			this.activate_publist();
			this.activate_initial_pub();
			this.activate_developer_datepickers();
      moopop.captureByRel();
      new Tips('.tooltip');
      new LoginHelp();
      new PressTicker();
      jq('.reveal').revealer();
      jq('.reveal_submit').revealer({hide_trigger: false});
    },
		datepicker:null,
		
		activate_developer_datepickers: function() {
		  var from_date = $('datefilter_from');
		  var to_date = $('datefilter_to');
		  if (from_date) {
		    new DatePicker('#datefilter_from', {
          defaultDate: new Date()
        });
		  }
		  if (to_date) {
		    new DatePicker('#datefilter_to', {
		      defaultDate: new Date()
		    });
		  }
		},
		activate_initial_pub: function(){
      var overlay = new Femtoverlay({
        element: '.learn_about_price',
        size: {x: 830, y: 400},
        onCreate: function() {
        }.bind(this),
        onOpen: function() {
          $('femtocontent').set('html', "<div class='overlay_wrapper'><a href='javascript:{}' class='close'>&nbsp;</a><h2 class='popup_header'>About Ad.ly Pricing</h2><p class='large'>Ad.ly's pricing algorithm picks what advertisers should pay you based on the quality of your feed. By setting your fair market price in our system, our algorithms give advertisers certain assurances, which lead to you getting you more ads. If you have questions about pricing, please email <a href='mailto:help@ad.ly'>help@ad.ly</a>.</p></div>");
          $('femtocontent').getElements('a.close').addEvent('click', function(e) { e.stop(); overlay.close.call(overlay); });
        }
      });
		},
		userInfo: function(el) {
      var id = el.get('user');
      var params = {
        ids: id,
        rand: (new Date().getTime())
      };

      new Request.JSON({
        url: '/webservice/?service=get_pub_profiles',
        onSuccess: function(json) {
					json = json[0];
          json.profile_image_url = json.profile_image_url || '/static/images/icons/default_profile_normal.png';
          var inner = ['about_publisher', 'categories', 'location', 'client_screen_name'].map(function(k) { return json[k] ? Templates.templateChunks[k] : ''; }).join('');
          var template = ['profile_image_url', 'display_name', 'client_followers_count'].map(function(k) { return json[k] ? Templates.templateChunks[k] : ''; }).join('');
          if (json.client_followers_count) { json.client_followers_count = intcomma(json.client_followers_count); }
					template += inner ? Templates.innerTemplate.substitute({info: inner}) : '';
					$('moreinfo_body').set('html', Templates.infoTemplate.substitute({pub_data: template}).substitute(json));
        }
      }).get(params);

    },
    activate_publist: function() {
      var self = this;
      if($$('.campaign-detail').length || $$('.message-detail').length ) {
        var moreinfoTip = new PopupTips({
            text:function(){
              return "<div id='moreinfo_body'></div>";
            },
            className:'moreinfoTip',
            fixed:true, 
            offset:{x:-600,y:-145}
        });
        moreinfoTip.addEvent('show', function(tip, el){
          self.userInfo(el);
          tip.fade('in');
        });
        $$('.colName').each(function(el){
          moreinfoTip.attach(el);
        });
      }
    },
		activate_sample_bitly_urls: function() {
		  var sampleUrlMessage = '<strong>This URL will be replaced with individualized bit.ly links<br/>so we can track each publisher\'s performance. You<br/>can click on the link to go to the orignal URL.</strong>';
		  var sampleUrlMessageJolly = '<strong>This URL will be replaced with individualized jol.ly links<br/>so we can track performance.<br/>You can click on the link to go to the orignal URL.</strong>';
		  // Set up sample bitly urls so that mouseover brings up a popup explainer box
		  new Tips('.sample-url', {
		    text: function() { return sampleUrlMessage; },
		    fixed: true,
		    className: 'tip_wrap tip-sample-url',
		    offset: { x: -80, y: 20 }
		  });
		  // Set up sample bitly urls so that mouseover brings up a popup explainer box
		  new Tips('.sample-url-jolly', {
		    text: function() { return sampleUrlMessageJolly; },
		    fixed: true,
		    className: 'tip_wrap tip-sample-url',
		    offset: { x: -80, y: 20 }
		  });
		},
        activate_coming_soon_urls: function() {
          var sampleUrlMessage = '<strong>Coming soon.</strong>';
          new Tips('.comingSoon', {
              text: function() { return sampleUrlMessage; },
              fixed: true,
              className: 'tip_wrap tip-sample-url',
              offset: { x: 50, y: 60 }
          });
        },

    rounded_boxes: function() {
      var corners = document.createDocumentFragment();
      (4).times(function(i) { corners.appendChild(new Element('span', {'class': 'r' + (i+1)})); });
      document.getElements('.rounded_box, ul.campaign_list li.campaign').each(function(box) { box.appendChild(corners.cloneNode(true)); });
    },
    hook_table_cells: function(){
      // clicks on table rows with links will take you to those links
      adly.utils.bodyEvent('.campaign-name', 'click', tableCellClick);
      adly.utils.bodyEvent('.message-name', 'click', tableCellClick);
      function tableCellClick(e){
        var el = e.target || e.srcElement;
        var anchors = el.getElementsByTagName('a');
        if(anchors.length){
          var anchor = anchors[0];
          if(anchor){
            location.href = anchor.href;
          }
        }
      }
    },

    activate_dependables: function(target) {
      target = target || document.getElements('.dependable');

      target.each( function(dependable) {
        var parent_name = dependable.className.match(/depends_on_(\w+)/)[1];
        var depend_value = dependable.className.match(/depend_value_(\w+)/)[1];

				if(!dependable.getParent('form'))
					return;

        dependable.getParent('form').getElements('input[name=' + parent_name + '], select[name=' + parent_name + ']').each( function(input) {
          input.addEvent(((input.get('tag') == 'select') ? 'change' : 'click'), function(e) {
            if (dependable.getStyle('display') != 'block' && ((input.value == depend_value) && (/(hidden|text)/.test(input.get('type')) || input.checked))) { /* show */
              dependable.addClass('visible');
              if (input.retrieve('pre_selected')) {
                input.eliminate('pre_selected');
              } else {
                dependable.highlight();
                if (dependable.getElements('input, select')) { $try(dependable.getElements('select, input')[0].focus()); }
              }
            } else if (input.value != depend_value || input.checked === false) { /* hide */
              input.eliminate('pre_selected');
              dependable.removeClass('visible');
            }

            dependable.fireEvent('dependable::update');
          });

          if (input.checked || input.get('checked') == 'checked' || input.selectedIndex > 0 || (/(hidden|text)/.test(input.get('type')) && input.get('value') == depend_value)) { input.store('pre_selected', true).fireEvent((input.get('tag') == 'select') ? 'change' : 'click'); }
        });
      });

      return target;
    },

    activate_collapsibles: function(target) {
      target = target || document.getElements('ul.campaign_list li.campaign, div.campaign_section');

      target.addClass('collapsible').getElement('h2, h3').addEvent('click', function() { this.getParent('.collapsible').toggleClass('collapsed'); });
    },

    activate_campaign_moreinfo: function() {
      document.getElements('.publisher input.plain_button').each( function(input) {
        input.addEvent('click', function() {
          var cm = new CampaignManager();
          cm.services.userInfo.call(cm, input.getPrevious('input[type=hidden]').get('value'));
        });
      });
    },

    activate_autoclear_fields: function(target) {
      target = target || document.getElements('input.autoclear');
      if (Browser.Engine.trident) return;

      target.each(function(field) {
        field.store('type', field.get('type')).retrieve('reset', function(){
          field.set({
            'value': document.getElement('label[for=' + field.get('id') + ']').get('text'),
            'type': 'text',
            'events': {
              'focus': function() { this.set('value', '').removeClass('empty').removeEvent('focus', arguments.callee); },
              'keydown': function() { this.removeClass('empty').removeClass('error'); this.set('type', this.retrieve('type')) },
              'blur': function() { if (!/\w+/.test(this.get('value'))) this.retrieve('reset')(); }
            }
          }).addClass('empty');
        })();
      });
    },

    set_up_campaign: function() {
      if ($('campaign_form')) {
        var container = $('campaign_selector');

        SponsorLab.campaign = new CampaignManager({
          mode: container ? 'list' : 'manage',
          container: container,
          campaign_json: (window.campaign_json) ? window.campaign_json : null
        });
      }
    },

    hook_settings: function() {
      SettingsManager.init('.settings_trigger');
    },

    hook_signup: function() {
      SignupOptions.init('.signupPubPage');
    },

    hook_payout_options: function() {
      document.getElements('ul.profile_payout_sel li>a').addEvent('click', function(e) {
        e.stop();
        document.getElement('input[name=paymentmethod]').set('value', this.get('href').match(/#(\w+)$/)[1]).fireEvent('click');
      });
    },

    hook_publisher_change_response: function() {
        document.getElements('.change_response').addEvent('click', function(e) {
            var target = $(e.target);
            var campaignAd = target.getParent('.campaign_ad');

            campaignAd.getElement('.campaign_ad_status').setStyle('display', 'none');
            campaignAd.getElement('.campaign_ad_set_status').setStyle('display', 'block');
            campaignAd.getElement('.campaign_ad_sent').setStyle('display', 'none');
            campaignAd.getElement('.campaign_ad_sent_update').setStyle('display', 'block');
        });
    },

    hook_single_submit: function() {
      $$('.single_submit').addEvent('click', function(event){
        var target = event.target;
        target.clone().inject(target, 'after').set('disabled', true);
        target.setStyle('display', 'none');
        var cancel_button = $('cancel');
        if (cancel_button){
          cancel_button.clone()
            .inject(cancel_button, 'after')
            .addClass('disabled', true)
            .removeAttribute('href');
          cancel_button.setStyle('display', 'none');
        }
      });
    },

    check_payment_methods: function() {
      if (this.campaign && $('payment_select') && $('payment_select').getElements('input[type=radio]').length > 1) {
        var c_total = this.campaign.getTotalPrice();
        if (c_total < 1000) { $('payment_select').getElements('input[type=radio]')[1].set('disabled', 'disabled'); }
        else if (c_total > 5000) { $('payment_select').getElements('input[type=radio]')[0].set('disabled', 'disabled'); }
      }
    },

    activate_payment_cards: function() {
      // Set up interaction with choosing saved credit cards or entering a new one
      var card_choices = jq('#saved_card_form');
      if (card_choices.length) {
        var new_cc_form = jq('#new_cc');
        // Set initial hidden state of form based on selections
        if (card_choices.find('input[type=radio]:checked').attr('value')) {
          new_cc_form.hide();
        } else {
          new_cc_form.show();
        }
        // Set up to display/hide the new card form based on selections
        card_choices.find('input[type=radio]').click(function(e) {
          if (jq(this).attr('value')) {
            // Selected a saved card; hide the new card form
            new_cc_form.slideUp(400);
          } else {
            // Selected use new card; show the new card form
            new_cc_form.slideDown(400);
          }
        });
      }
    },

    activate_message_previews: function() {
      // Tacks on additional functionality to the standard pagination used for the messages
      // by updating the "message 1 of 4" text as you click through them.
      var pagination_links = $$('.summary_campaign_messages .pagination a');
      pagination_links.addEvent('click', function(e) {
        // Determine the number of the old selected message
        var old_message = $$('.summary_campaign_messages .campaign_messages .message_node')
          .filter(function(message, i) {
            return message.getStyle('display') == 'block';
          })[0];
        old_message = old_message.get('id').split('_')[1].toInt();
        // Determine whether to go prev or next
        var prev = this.hasClass('prev');
        var new_message = prev ? old_message - 1 : old_message + 1;
        // Update the message number display
        $(document).getElement('.message_summary_header .current-message')
          .set('html', new_message.toString());
      });
    }
  };

  var SelectBox = function(id, onclick, arg){
    var self = this;
    function init(id, onclick, arg) {
      self.el = jq(id);
      if(!self.el){ return; }
      var spanSelected = jq('span.selected', self.el);
      var removeTip = function() {
        self.el.removeClass('openSelect');
        jq(document).unbind('click', removeTip);
      };

      if(self.el) {
        jq('li', self.el).click(function(e) {
          e.preventDefault();
          e.stopPropagation();
          jq(this).parents('ul').find('li.selected').removeClass('selected');
          jq(this).addClass('selected');
          //el.getElement('span.selected').set('text', 'Filter by ' + e.target.get('text') );
          removeTip();
          onclick(id, e);
        });
        spanSelected.click(function(e) {
          if(!self.el.hasClass('openSelect')){
            var borders = 2;
            var padding = 35 + 6 + borders; //default padding
            var width = self.el.width();
            //self.el.setStyle('width', width)
            spanSelected.css('width', width - padding);
            self.el.find('ul').css('width', width - borders);
          }
          self.el.toggleClass('openSelect');
          e.preventDefault();
          e.stopPropagation();
          jq(document).bind('click', removeTip);
        });
      }
    }
    init(id, onclick, arg);
  };

  var FilterBox = new Class({
      Implements: [Events],
      initialize: function(id, onclick, arg) {
        var self = this;
        self.el = jq(id);
        var removeTip = function() {
          self.el.find('.filter_sel_holder').removeClass('open');
          jq(document).unbind('click',removeTip);
        };

        if (self.el) {
          self.el.find('a').click(function(e) {
            var clickedEl = jq(this);
            e.stopPropagation();
            e.preventDefault();
            clickedEl.closest('ul').find('li.selected').removeClass('selected');
            clickedEl.parents('li').addClass('selected');
            var prefix = 'Filter by ';
            if (clickedEl.attr('id').slice(0, 4) != 'cate') {
              prefix = '';
            }
            self.el.find('span.selected').text('Filter by ' + jq(e.currentTarget).text() );
            removeTip();
            // Kluge to get this working with getList for filters, which expects options object
            if (self.el.parent().attr('id') == 'filters_bar') {
              onclick({});
            }else{
              onclick(id, e);
            }
          });
          self.el.find('span.selected').click(function(e) {
            self.el.find('.filter_sel_holder').toggleClass('open');
            e.stopPropagation();
            e.preventDefault();
            jq(document).bind('click', removeTip);
          });
        }
      }
  });

  var SettingsManager = {
    serviceTemplate: "/webservice/?service=settings&block={block}",
    overlay: null,
    loadedContent: null,
    shouldRefresh: false,
		disabled: false,

    init: function(target, initial) {
      this.overlay = new Femtoverlay({
        element: target,
        size: {x: 830, y: 200},
        onCreate: function(event) {
          this.shouldRefresh = false;
          var initial = event.target.getAttribute("initial");
          if (initial) {
            this.loadSection({ block: initial });
          }else {
            this.loadIndex();
          }
        }.bind(this),
        onOpen: this.loadContent.bind(this)
      });
    },

    loadIndex: function() {
      this.loadSection({ block: 'index' });
    },
		checkCount: function(){
			var checked = 0
			$$('.opt_group input').each(function(el){
				if(el.get("checked")) { checked++; }
			});

			if(checked >= 4) {
				$$('.pubprofile_form_category').each(function(el){
					if(!el.get("checked")) {
						el.set("disabled", true);
					}
				});
			} else {
				$$('.opt_group input').each(function(el){
					el.set("disabled", false);
				});
			}

		},

    loadSection: function(options) {
      var self = this;

      new Request.HTML({
        url: this.serviceTemplate.substitute({block: options.block}),
        onSuccess: function(responseTree) {
          self.loadedContent = responseTree;
          self.shouldRefresh = self.shouldRefresh || $chk(this.getHeader('X-Splab-Refresh'));
          self.loadContent.call(self);

					if(options.block == "profile") {
						$$('#femtocontent .opt_group input').addEvent('click', self.checkCount);
						self.checkCount();
					}
        }
      }).get();
    },

    loadContent: function() {
      var self = this;

      if ($('femtocontent') && this.loadedContent) {
        if ($type(this.loadedContent) == 'string') {
          $('femtocontent').empty().set('html', this.loadedContent);
        } else {
          $('femtocontent').empty().adopt(this.loadedContent);
        }

        SponsorLab.activate_dependables($('femtocontent').getElements('.dependable')).addEvent('dependable::update', function() { self.reposition.call(self, true); });
        // events
        this.reposition();
        $('femtocontent').getElements('a.close').addEvent('click', this.hide.bindWithEvent(this));
        $('femtocontent').getElements('ul.settings_sections li a').addEvent('click', function(e) {
          if (/#/.test(this.get('href'))) {
            e.stop();
            this.addClass('waiting');
            self.loadSection.call(self, { block: this.get('href').match(/#(\w+)/)[1] });
          }
        });
        $('femtocontent').getElements('a.go_back').addEvent('click', function(e) { e.stop(); self.loadIndex.call(self); });
        $('femtocontent').getElements('form').set('send', {
          onSuccess: function(responseHTML) {
            self.loadedContent = responseHTML;
            self.shouldRefresh = self.shouldRefresh || $chk(this.getHeader('X-Splab-Refresh'));
            self.loadContent.call(self);
          }
        }).addEvent('submit', function(e) { e.stop(); this.send(); });
      }
    },

    reposition: function(smooth) {
      this.overlay.reposition({y: $('femtocontent').getElement('div.overlay_wrapper').getScrollSize().y}, smooth);
    },

    hide: function(e) {
      if (e) { e.stop(); }
      if (this.shouldRefresh) {
        window.location.href = window.location.href;
      } else if (this.overlay) {
        this.overlay.close();
      }
    }
  };


  var CampaignManager = new Class({
      Implements: [Options, Events],
      moreinfoTip: null,
      infoTemplate: '<div class="user_info">{pub_data}</div>',
      innerTemplate: '<dl class="info">{info}</dl>',
      templateChunks: {
        profile_image_url: '<img src="{profile_image_url}" alt="" class="thumbnail" />',
        display_name: '<h1>{display_name}</h1>',
        client_followers_count: '<p class="stats">{client_followers_count} Followers, {twitter_avg_tweets} Avg. Daily Posts</p>',
        about_publisher: '<dt>About Publisher:</dt><dd>{about_publisher}</dd>',
        categories: '<dt>Categories:</dt><dd>{categories}</dd>',
        location: '<dt>Location:</dt><dd>{location}</dd>',
        client_screen_name: '<dt>Profile Page:</dt><dd><a href="{profile_url}" target="_blank">{profile_url}</a></dd>',
        add_user: ''
      },
      help_messages: {
        weekly_fee: 'message to explain what this column is for'
      },
      users: {},
      shouldRender: true,
      options: {
        onAddUser: $empty,
        onRemoveUser: $empty,
        onBeforeRemoveUser: $empty,
        mode: 'list',
        campaign_json: null,
        container: null,
        owner: null,
        services: {
          getListURL: '/webservice/?service=get_pub_list',
          userInfoURL: '/webservice/?service=get_pub_profiles'
        }
      },
      overlay_min_y: 300,
      //overlay: {},
      popupContent: null,
      current_node: null,
      messageTemplate:'',
      only_added: false,
      payment_page: false,

      initPopup: function(target, only_added) {
        var self = this;
        var node = self.message_id;
        jq(target).click(function(){
          self.only_added = only_added;
          self.loadIndex(node);
          ///////
          jq('#campaign_form').css({'display':'none'});
          jq('#campaign_form_submit').css({'display':'none'});
          jq('#popup_content').css({'display':'block'}).html(self.popupContent);

          // Intercept the "form submit" for publisher filtering by name (for standalone publisher list page)
          jq('#search_box_form').submit(function(e) {
            self.services.getList.apply(self);
            return false;
          }.bind(self));

          document.body.scrollTo(0,0);

          if(self.payment_page == false	)
            self.renderUsersFragment();

          jq('#popup_done').click(function(){
            jq('#popup_content').css({'display':'none'});
            jq('#campaign_form').css({'display':'block'});
            jq('#campaign_form_submit').css({'display':'block'});
            document.body.scrollTo(0, jq('#message_'+node).offset().top);
          });
          var updateLabel = function(pos, label) {
            pos.minpos = Math.round(pos.minpos / 1000);
            pos.maxpos = Math.round(pos.maxpos / 1000);

            if(pos.maxpos == 1000) {
              pos.maxpos = "1 million+";
            } else {
              pos.maxpos += "k";
            }

            jq(label).html(pos.minpos + "k - " + pos.maxpos);
          };

          // $.price_slider = new Slider($('slider_price'), $('slider_price_min'),$('slider_price_img'), {
          // start: 10000,
          // end: 1000000,
          // offset:6,
          // snap:false,
          // onChange: function(pos){
          // updateLabel(pos,'slider_price_label');
          // }
          // }, $('slider_price_max')).setMin(10000).setMax(1000000).addEvent('complete',self.services.getList.bind(self));

          // $.follower_slider = new Slider($('slider_follower'), $('slider_follower_min'),$('slider_follower_img'), {
          // start: 10000,
          // end: 1000000,
          // offset:6,
          // snap:false,
          // onChange: function(pos){
          // updateLabel(pos,'slider_follower_label');
          // }
          // }, $('slider_follower_max')).setMin(10000).setMax(1000000).addEvent('complete',self.services.getList.bind(self));;

          new FilterBox('#categories_sel_1', self.services.getList.bind(self), self);
          new FilterBox('#categories_sel_2', self.services.getList.bind(self), self);

          new FilterBox('#price_sel_1', self.services.getList.bind(self), self);
          new FilterBox('#price_sel_2', self.services.getList.bind(self), self);

          new FilterBox('#followers_sel_1', self.services.getList.bind(self), self);
          new FilterBox('#followers_sel_2', self.services.getList.bind(self), self);

          if ($('reset_all')) {
            $('reset_all').addEvent('click', function(){
              $$('#search_box_form input').each(function(el){
                el.set('value',el.get('rel'));el.addClass('def');
              });
              $$('#categories_sel, #categories_sel_1, #categories_sel_2, #price_sel_1, #price_sel_2, #followers_sel_1, #followers_sel_2').each(function(el){
                el.getElement('span').set("html", el.getElement('div div a').get('html'));
                if(el.getElement('li.selected')) {
                  el.getElement('li.selected').removeClass('selected');
                }
              });
              self.services.getList.apply(self);
            });
          }

          var defs = new dwDefaults({
              collection: jq('#search_box_form input')
          });

          self.services.getList.apply(self);
          SponsorLab.activate_dependables(
            $('popup_content').getElements('.dependable')).addEvent('dependable::update',
              function() {
                self.reposition.call(self, true); 
            });
        });
      },
      loadIndex: function(node) {
        var self = this;
        if(this.payment_page) {
          $$('.message_node').each(function(el,i){
            if(el.getStyle("display") == "block") {
              self.current_node = i;
              return false;
            }
          });
        } else {
          this.current_node = node;
        }
        this.popupContent = this.popupContent || jq('#popup_content').html();
        $('popup_content').empty();
      },
      reposition: function(smooth) {
        if(!$('femtocontent'))
          return;
        var size_y = $('femtocontent').getElement('div.overlay_wrapper').getScrollSize().y;
        if(this.overlay['overlay_'+this.current_node])
          this.overlay['overlay_'+this.current_node].reposition({y: size_y > this.overlay_min_y ? size_y : this.overlay_min_y}, smooth);

        if(this.overlay['overlay_'+this.current_node+'_added'])
          this.overlay['overlay_'+this.current_node+'_added'].reposition({y: size_y > this.overlay_min_y ? size_y : this.overlay_min_y}, smooth);
      },
      message_id: 0,
      // This is for the payment page
      viewAddedMessages: function() {
        var self = this;

        $$(".campaign_messages .message_node").each(function(el, i){
          self.users['message_'+i] = [];
          el.getElements('.assigned_publishers li').each(function(li){
            self.users['message_'+i].push({"id":li.get("user_id")});
          });
        });

        this.initPopup('.view_more', true);
      },
      addMessage: function(initial, shortener) {
        var self = this;
        var internal_sales = window.internal_sales ? true : false;
        var node = jq('<div class="message createBlock" id="message_' + this.message_id + '"/>').html(
          this.messageTemplate
        ).insertBefore('#add_message_field');

        if(!this.message_id) {
          jq('a.remove_message', node).remove();
        }else{
          jq('a.remove_message', node).click(function(){
            delete self.users['message_'+self.message_id];
            node.remove();
          });
        }
        // Set message number
        jq('.message_num', node).text(" " + (this.message_id + 1));

        // Set correct name on csv importer
        jq('.publisher_csv', node).attr('name', 'publisher_csv_'+this.message_id);

        // Set correct ids for the shortener chooser
        jq('#adly_shortener', node)
          .attr('id', 'adly_shortener_' + this.message_id)
          .attr('name', 'shortener_' + this.message_id);
        jq('#bitly_shortener', node)
          .attr('id', 'bitly_shortener_' + this.message_id)
          .attr('name', 'shortener_' + this.message_id);

        // Set correct tweet_method on messages
        jq.each(jq('.tweet_method', node), function(index, method){
          method = jq(method);
          method.attr('name', 'tweet_method_'+self.message_id);
          method.attr('id', method.attr('id') + self.message_id);
          method.parent().find('label').attr('for', method.attr('id'));
        });

        this.users['message_'+this.message_id] = [];
        this.initPopup('#message_'+this.message_id+' .add_publisher', false);

        this.initPopup('#message_'+this.message_id+' .update_publishers', true);

        new FilterBox(jq('.timezone', node), function(id, e){
          jq('span.selected', id).text( e.target.get('text'));
          jq('.scheduled_timezone').val(e.target.get('text'));
        }, self);
        new FilterBox(jq('.approved_timezone', node), function(id, e){
          var target = jq(e.currentTarget);
          jq('span.selected', id).text(target.text());
          jq('.instant_timezone', node).val(target.text());
        }, self);
        if (initial) {
          if (initial.scheduled_timezone) {
            jq('.scheduled_timezone', node).val(initial.scheudled_timezone);
            jq('.send_by_time_options span.selected', node).text(initial.scheduled_timezone);
          }
          if (initial.instant_timezone) {
            jq('.instant_timezone', node).val(initial.instant_timezone);
            jq('.send_by_approved_options span.selected', node).text(initial.instant_timezone);
          }
        }

        jq('.pub_time', node).attr('id', 'pub_time_'+this.message_id);
        jq('.instant_expire_time', node).attr('id','instant_expire_time_'+this.message_id);

        new dwDefaults({
            collection: jq('#message_'+this.message_id+' textarea')
        });

        // Calculate dates for defaults, mins, maxes
        function format_date(date) {
          return (date.getMonth() + 1).toString() + '/' + date.getDate().toString() + '/' + date.getFullYear().toString();
        }
        var day_ms = 1000 * 60 * 60 * 24;
        var today_ms = new Date().getTime();
        var today = format_date(new Date(today_ms));
        var today_plus_1 = format_date(new Date(today_ms + day_ms));
        var today_plus_2 = format_date(new Date(today_ms + (2 * day_ms)));
        var today_plus_7 = format_date(new Date(today_ms + (7 * day_ms)));

        // Set dates initially if editing an existing campaign
        if (initial && initial.scheduled_start_date) {
          jq('.scheduled_start_date', node).val(unescape(initial.scheduled_start_date));
        }
        if (initial && initial.instant_expire_date) {
          jq('.instant_expire_date', node).val(unescape(initial.instant_expire_date));
        }

        // Create datepickers for this message
        new DatePicker('#message_' + this.message_id + ' .instant_expire_date', {
            defaultDate: today_plus_2,
            minDate: internal_sales ? today : today_plus_1
        });
        new DatePicker('#message_' + this.message_id + ' .scheduled_start_date', {
            defaultDate: today_plus_2,
            minDate: internal_sales ? today : today_plus_1
        });

        // Set times initially if editing an existing campaign
        if (initial && initial.scheduled_start_time) {
          jq('.pub_time', node).val(unescape(initial.scheduled_start_time));
        }
        if (initial && initial.instant_expire_time) {
          jq('.instant_expire_time', node).val(unescape(initial.instant_expire_time));
        }

        // Create timepickers for this message
        new TimePicker('#message_' + this.message_id + ' .instant_expire_time', {
            periodNames: ['am', 'pm'],
            minTime: internal_sales ? null : '7:00 am',
            maxTime: internal_sales ? null : '10:00 pm',
            choiceInterval: 15,
            constrainChoices: false
        });
        new TimePicker('#message_' + this.message_id + ' .pub_time', {
            periodNames: ['am', 'pm'],
            minTime: internal_sales ? null : '7:00 am',
            maxTime: internal_sales ? null : '10:00 pm',
            choiceInterval: 15,
            constrainChoices: false
        });

        jq('.send_as_approved', node).click(function(){
          jq('.send_by_time_options', node).css('display', 'none');
          jq('.send_by_approved_options', node).css('display', 'block');
        });

        if(jq('.send_as_approved', node).attr('checked')) {
          jq('.send_by_approved_options', node).css('display','block');
        }

        new PreviewGen('#message_'+this.message_id, shortener);

        jq('.send_by_time', node).click(function(){
          jq('.send_by_time_options', node).css('display','block');
          jq('.send_by_approved_options', node).css('display','none');
        });

        if(jq('.send_by_time', node).attr('checked')) {
          jq('.send_by_time_options', node).css('display','block');
        }

        this.message_id++;
      },

      initialize: function(options) {
        this.setOptions(options);
        var self = this;

        /*
         CampaignManager.moreinfoTip = new PopupTips({text:function(){return "<div id='moreinfo_body'></div>";},className:'moreinfoTip',fixed:true, offset:{x:-600,y:-145}});
         CampaignManager.moreinfoTip.addEvent('show',function(tip,el){
         self.services.userInfo.apply(self, [el, self]);
         tip.fade('in');
  });
  */
        if (!$('campaign_form')) { return; }

        //setup campaign select
        var existing_campaign = jq('#existing_campaign');
        var existing_campaign_radio = jq('#existing_campaign_radio')
        var existing_campaign_select = jq('#existing_campaign_select')
        if(existing_campaign && this.options.campaign_json){
          if('existing_campaign' in this.options.campaign_json){
            existing_campaign.value = this.options.campaign_json.existing_campaign;
            existing_campaign_radio.click();
          }
          var json = this.options.campaign_json;
          if('existing_campaign_name' in json){
            var campaign_name = json.existing_campaign_name || json.campaign_name;
            var existing_campaign_name = jq('#existing_campaign_name');
            existing_campaign_name.val(campaign_name);
            jq('#existing_campaign').val(json['existing_campaign']);
            existing_campaign_select.find('.selected').html(campaign_name);
          }
        }

        if ($('pub_list')) {
          new FilterBox('#categories_sel_1', self.services.getList.bind(self), self);
          new FilterBox('#categories_sel_2', self.services.getList.bind(self), self);

          new FilterBox('#price_sel_1', self.services.getList.bind(self), self);
          new FilterBox('#price_sel_2', self.services.getList.bind(self), self);

          new FilterBox('#followers_sel_1', self.services.getList.bind(self), self);
          new FilterBox('#followers_sel_2', self.services.getList.bind(self), self);

          $('reset_all').addEvent('click', function(){
            $$('#search_box_form input').each(function(el){
              el.set('value',el.get('rel'));el.addClass('def');
            });
            $$('#categories_sel, #categories_sel_1, #categories_sel_2, #price_sel_1, #price_sel_2, #followers_sel_1, #followers_sel_2').each(function(el){
              el.getElement('span').set("html", el.getElement('div div a').get('html'));
              if(el.getElement('li.selected')) {
                el.getElement('li.selected').removeClass('selected');
              }
            });
            self.services.getList.apply(self);
          });

          var defs = new dwDefaults({
              collection: jq('#search_box_form input')
          });
        }

        // Set up publisher list page search box
        new dwDefaults({
            collection: jq('#search_box_cont input.text')
        });
        // Intercept the "form submit" for publisher filtering by name (for standalone publisher list page)
        if ($('search_box_form')) {
          $('search_box_form').addEvent('submit', function(e) {
            this.services.getList.apply(this);
            return false;
          }.bind(this));
        }
        // Load initial publisher list for pub list page
        if(document.location.href.indexOf('/publisher-list') != -1)
          this.services.getList.apply(this);

        // Set up campaign selection drop-down
        new adly.selectBox('#existing_campaign_select', function(id, e){
          var target = e.currentTarget;
          if(jq(target).is('li')){
            target = jq('a', target);
          }
          jq('span.selected', id).text(target.text());
          jq('#existing_campaign').val(target.attr('id'));
          jq('#existing_campaign_name').val(target.text());
        }, self);

        // Set up for adding messages
        if ($('message_template')) {
          this.messageTemplate = $('message_template').get('html');
          $('message_template').destroy();
          $('add_message').addEvent('click',
            function(){self.addMessage();}
          );

          // If there is an existing campaign being created, load its info; otherwise, start fresh
          var json = this.options.campaign_json;
          if (json && json.items && json.items.length > 0) {
            this.loadCampaign(json);
          } else {
            this.addMessage();
          }
        } else if($('message_0')) {
          this.payment_page = true;
          this.viewAddedMessages();
        }

        // When user hits "next" button, serialize messages as JSON and send to server
        var campaign_form_submit = $('campaign_form_submit');
        if (campaign_form_submit) {
          jq('#campaign_form_submit').submit(function(e) {
            // Construct the JSON object
            var json_array = [];
            jq.each(jq('#campaign_form').find('div.message'), function(i, message) {
              // For each message, serialize its form elements and hidden publishers array
              // TODO: convert away from mootools
              var j = $(message).toJSON();
              message = jq(message);
              j.message_element = message.attr('id');

              // Make message blank if default
              if (message.find('textarea').val() == message.find('textarea').attr('rel')) {
                j.message = '';
              }
              var users = [];
              jq.each(self.users[message.attr('id')], function(index, u){
                users.push(u.id);
              });

              // Rename radio buttons (workaround input grouping issues)
              for(var item in j){
                if(j.hasOwnProperty(item)){
                  if(item.indexOf('tweet_method') >= 0){
                    j['tweet_method'] = j[item];
                  }else if(item.indexOf('shortener') >= 0){
                    j['shortener'] = j[item];
                  }
                }
              }
              j.publishers = users;
              json_array.push(j);
            });
            var existing_campaign = $('existing_campaign');
            var existing_campaign_val = existing_campaign ? existing_campaign.get('value') : '';
            var existing_campaign_name = $('existing_campaign_name');
            var json_string = JSON.encode({
                "campaign_name": $('campaign_name').get('value'),
                'new_campaign': existing_campaign_val ? false : true, // need this for performance create to work
                'existing_campaign': existing_campaign_val,
                'existing_campaign_name': existing_campaign_name ? existing_campaign_name.get('value') : '',
                "campaign_saved_id": $('campaign_saved_id').get('value'),
                "campaign_price": $('message_total_price').get('value'),
                "campaign_publishers": $('message_total_publishers').get('value'),
                "campaign_followers": $('message_total_followers').get('value'),
                "items": json_array });

            // Validate that the input appears valid
            var csv_value = false;
            var csv_found = false;
            jq.each(jq('.publisher_csv'), function(index, csv){
              csv_found = true;
              if(csv.value){
                csv_value = true;
              }
            });
            var valid = true;
            if (!csv_found || !csv_value){
              valid = self.validateCampaign(json_string);
            }

            if (!valid) {
              return false;
            }

            // Insert the JSON object in a hidden form element so it gets submitted
            jq('#campaign_form_submit').find('input[name=campaign_all]').val(json_string);
          });
        }
        var new_campaign_radio = jq('#new_campaign_radio')
        var campaign_name = jq('#campaign_name')
        if(existing_campaign_radio){
          existing_campaign_radio.click(function(){
            existing_campaign_select.css('display','block');
            campaign_name.css('display','none');
          });
          if(existing_campaign_radio.attr('checked')) {
            existing_campaign_select.css('display','block');
            campaign_name.css('display','none');
          }

          new_campaign_radio.click(function(){
            existing_campaign_select.css('display','none');
            campaign_name.css('display','block');
            jq('#existing_campaign').val('');
            jq('#existing_campaign_name').val('');
          });
          if(new_campaign_radio.attr('checked')) {
            existing_campaign_select.css('display','none');
            campaign_name.css('display','block');
            jq('#existing_campaign').val('');
            jq('#existing_campaign_name').val('');
          }
        }

        // When the user submits the form to complete the campaign, run the
        // payment processing in the background
        /*var campaign_payment_submit = $('campaign_payment_submit');
        if (campaign_payment_submit) {
          campaign_payment_submit.addEvent('submit', function(e) {
            e.stop();
            var overlay = new Femtoverlay({
                closable: false,
                size: {x: 525, y: 300},
                onOpen: function() {
                  $('femtocontent').set('html', "<div class='overlay_wrapper'><h2 class='popup_header'>Creating your campaign and processing your payment</h2><p class='large'>Please wait while we create your campaign and proccess your payment.</p><p class='large'>This may take a few moments. <img src='/static/images/icons/ico_spin.gif'/></p></div>");
                }
            });
            overlay.open();

            setErrorMessage = function(message){
              $('payment_error').set('html', message);
              $('payment_error_list').setStyle('display', message ? 'block' : 'none');
              $$('.payment_form .errorlist').destroy();
              if (message){
                $$('.btn_complete_campaign').each(function(btn){
                  if(btn.get('disabled')){
                    btn.destroy();
                  }else{
                    btn.setStyle('display', 'block');
                  }
                });
                overlay.close();
              }
            };

            new Request.JSON({
                url: campaign_payment_submit.get('action'),
                data: campaign_payment_submit,
                onRequest: function(){
                  setErrorMessage('');
                },
                onSuccess: function(response){
                  var json = JSON.decode(response);
                  if (response.error){
                    setErrorMessage(response.error);
                    return;
                  }

                  if (response.redirect){
                    window.location = response.redirect;
                    return;
                  }

                  if (response.html){
                    campaign_payment_submit.set('html', response.html);
                    overlay.close();
                    return;
                  }

                  var task_id = response.task_id;
                  var completed_url = response.completed_url;
                  new TaskPoller({
                      timeout: 120,
                      interval: 2,
                      onSuccess: function(result){
                        // replace the place holder campaign id of 1 with the actual id
                        var url = completed_url.replace('1', result);
                        window.location = url;
                      },
                      onFailure: function(result){
                        setErrorMessage(result);
                      },
                      onTimeout: function(){
                        var message = "We're sorry, but we timed out while waiting for your campaign to be processed.  Feel free to send an email to <a href='mailto:help@ad.ly'>help@ad.ly</a> if you would like us to look into this error.  Otherwise you may attempt to submit your campaign again after a few moments.";
                        setErrorMessage(message);
                      }
                  }).start(task_id);
                },
                onFailure: function(response){
                  setErrorMessage(response.status + ': ' + response.statusText);
                }
            }).send();
          });
        }*/
      },

      validateCampaign: function(json_string) {
        // Goes over the entire campaign creation form to check that it appears valid
        // If it validates, returns true;
        // If not, returns false and displays error messages
        var internal_sales = window.internal_sales ? true : false;
        var short_url_re = new RegExp(window.short_url_re, 'igm');
        var invalid_url_re = new RegExp(window.invalid_url_re, 'igm');
        var url_re = new RegExp(window.url_re, 'igm');
        var MIN_CAMPAIGN_PRICE = 25;
        var error_messages = {
          campaign_name_empty: 'Please enter a name for this campaign',
          campaign_name_length: 'Your campaign name is too long. Please keep it less than 64 characters.',
          campaign_min_price: 'Campaigns must be for at least a $25 spend',
          message_content_empty: 'Please fill in a message',
          message_content_length: 'Please keep your message under 140 characters',
          message_publishers_empty: 'Please select one or more publishers for your message',
          message_short_url: 'Please do not use short URL services. Include the original URL in your message, and we will automatically create short URLs to track each publisher individually.',
          message_invalid_url: 'Twitter does not properly handle URLs ending with punctuation (a period, comma, etc.) Please remove any such characters to ensure that your links will work properly.',
          message_missing_url: 'Please include a URL in your message.'
        }
        var form = JSON.decode(json_string);
        var total_price = 0;
        var errors = [];
        // Check for campaign name
        if (!form.campaign_name && !form.existing_campaign) {
          errors.include(error_messages.campaign_name_empty);
        }
        else if (form.campaign_name.length > 64) {
          errors.include(error_messages.campaign_name_length);
        }
        errors = {
          'campaign': errors,
          'messages': []
        };
        // Loop over messages to check for content and publishers
        for (var i = 0; i < form.items.length; i++) {
          var message_errors = [];
          if (short_url_re.test(form.items[i].message)) {
            message_errors.include(error_messages.message_short_url);
          }
          if (invalid_url_re.test(form.items[i].message)) {
            message_errors.include(error_messages.message_invalid_url);
          }
          // test fails if we don't re-compile the regex
          url_re = new RegExp(window.url_re, 'igm');
          if(!url_re.test(form.items[i].message)){
            message_errors.include(error_messages.message_missing_url);
          }
          var chars = $(form.items[i].message_element).getElement('.chars_left').get('text').toInt();
          if (isNaN(chars) || chars < 0) {
            message_errors.include(error_messages.message_content_length);
          } else if (chars >= 140) {
            message_errors.include(error_messages.message_content_empty);
          }
          if (form.items[i].publishers.length < 1) {
            message_errors.include(error_messages.message_publishers_empty);
          }
          errors['messages'].push(message_errors);
          total_price += parseInt(form.items[i].total_price, 10);
        }
        // Check for min campaign price
        if (!internal_sales && total_price < MIN_CAMPAIGN_PRICE) {
          errors.campaign.push(error_messages.campaign_min_price);
        }
        jq('.errormsg').remove();
        var campaignError = false;
        var messagesError = false;
        // If there are errors, display them
        if (errors['campaign'].length) {
          campaignError = true;
          // Clear out any previous error messages
          var error_container = jq('#error_list');
          if (error_container) {
            error_container.html('');
            var div = jq('<div class="errormsg"/>');
            var ul = jq('<ul class="errorlist"/>');
            ul.appendTo(div);
            div.appendTo(error_container);
            for (var i = 0; i < errors['campaign'].length; i++) {
              var li = jq('<li/>').text(errors['campaign'][i]);
              li.appendTo(ul);
            }
          }
          // Scroll the window up to the error messages
          window.scrollTo(0, 0);
        }
        // insert individual message error
        var messageErrors = errors['messages'];
        for (var i = 0; i < messageErrors.length; i++) {
          if(messageErrors[i].length){
            var error_anchor = jq('#message_' + i);
            jq('#message_' + i + '_error').remove();
            var div = jq('<div id="message_' + i + '_error" class="errormsg adError"/>');
            var ul = jq('<ul class="errorlist"/>');
            ul.appendTo(div);
            jq.each(messageErrors[i], function(index, err){
              messagesError = true;
              var li = jq('<li/>');
              li.text(err).appendTo(ul);
            });
            div.insertBefore(error_anchor);
            div[0].scrollIntoView();
          }
        }
        return !campaignError && !messagesError;
      },

      loadCampaign: function(json) {
        var self = this;
        // Loads up the existing campaign creation form elements
        $('campaign_name').set('value', json.campaign_name);
        $('campaign_saved_id').set('value', json.campaign_saved_id);
        // Loop over messages and add them to the campaign
        for (var i = 0; i < json.items.length; i++) {
          var item = json.items[i];
          // Add the message html to the page
          this.addMessage(item, item.shortener);
          var msg = $('message_' + i);
          // Set the input elements
          msg.getElement('.campaign_ad_saved_id').set('value', item.campaign_ad_saved_id)
          msg.getElement('.tweet_message textarea')
          .fireEvent('focus')
          .set('value', item.message)
          .fireEvent('blur')
          .fireEvent('keypress');
          if (item.tweet_method == 0) {
            msg.getElement('input.send_as_approved')
            .set('checked', 'checked')
            .fireEvent('click');
          }
          else {
            msg.getElement('input.send_by_time')
            .set('checked', 'checked')
            .fireEvent('click');
          }
          msg.getElement('.instant_expire_time')
          .set('value', decodeURIComponent(item.instant_expire_time));
          msg.getElement('.pub_time')
          .set('value', decodeURIComponent(item.scheduled_start_time));
          if (item.scheduled_tweet_interval) {
            msg.getElement('.every_15')
            .set('checked');
          }
        }
        // Compile the list of required publisher ids
        var idList = [];
        json.items.each(function(msg) {
          msg.publishers.each(function(id) {
            idList.push(id);
          });
        });
        // Add the selected publishers for all messages
        this.services.getList.bind(this)({
            selected: idList.join(','),
            limit: idList.length,
            on_success: function(response_json) {
              // Load the publishers into each message
              json.items.each(function(msg, i) {
                self.current_node = i;
                msg.publishers.each(function(id) {
                  self.addUser.bind(self)(id);
                });
              });
            }
        });
      },

      addUser: function(id) {
        this.users['message_'+this.current_node].push(this.getLoadedUserFromId(id));
        this.globalUpdate();
        this.fireEvent('addUser');
      },

      removeUser: function(id) {
        this.fireEvent('beforeRemoveUser', id);
        this.users['message_'+this.current_node].erase(this.getSelectedUserFromId(id));

        this.globalUpdate();
        this.fireEvent('removeUser', id);
      },

      globalUpdate: function() {
        if (!this.shouldRender) { return; }

        if (this.options.mode != 'overlay') {
          if (document.getElement('input[name=publishers]')){
            document.getElement('input[name=publishers]').set('value', this.getSerializedPublishers());
          }
          this.renderUsersFragment();
        }
        if (this.options.container && this.options.container.getParents().every(function(el) { return el.getStyle('display') != 'none' })) {
          this.renderTable(null, {can_has_sort: (this.options.mode != 'overlay')});
        }
        if(this.users['message_'+this.current_node].length === 0) {
          $$("#message_"+this.current_node+" .update_publishers").setStyle("display","none");
        } else {
          $$("#message_"+this.current_node+" .update_publishers").setStyle("display","block");
        }
      },

      suspendRender: function() {
        this.shouldRender = false;
      },

      forceUpdate: function() {
        this.shouldRender = true;
        this.globalUpdate();
      },

      getCount: function() {
        if(!this.users['message_'+this.current_node])
          return [];
        return this.users['message_'+this.current_node].length;
      },

      isUserAdded: function(id) {
        if(!this.users['message_'+this.current_node])
          return [];
        return this.users['message_'+this.current_node].some(function(user) { return user.id == id; });
      },

      getLoadedUserFromId: function(id) {
        return this.loadedData.publishers.filter(function(user) {
          return user.id == id; 
        })[0];
      },

      getSelectedUserFromId: function(id) {
        if(!this.users['message_'+this.current_node])
          return null;
        return this.users['message_'+this.current_node].filter(function(user) { return user.id == id; })[0];
      },

      getSerializedPublishers: function() {
        if(!this.users['message_'+this.current_node])
          return '';
        return this.users['message_'+this.current_node].length ? JSON.encode(this.users['message_'+this.current_node]) : '';
      },

      getTotalFollowers: function(key) {
        key = key || 'message_'+this.current_node;
        if(!this.users[key])
          return 0;
        var ret = 0;
        this.users[key].each(function(user) { ret += user.client_followers_count; });
        return ret;
      },

      getTotalPrice: function(key) {
        key = key || 'message_'+this.current_node;
        if(!this.users[key])
          return 0;
        var ret = 0;
        this.users[key].each(function(user) { ret += user.price_per_tweet; }); //weekly_fee
        return ret / 100;
      },

      validate: function(form) {
        var valid = (this.users['message_'+this.current_node].length > 0);
        if (!valid || (document.getElement('input[name=publishers]') && (document.getElement('input[name=publishers]').get('value') === ''))) { window.alert('Please select publisher(s) to sponsor before continuing'); }

        return valid;
      },

      isUserVisible: function(id) {
        return $chk($('campaign_users_area').getElements('ul.user_portraits li').filter(function(user) { return user.retrieve('user').id == id})[0]);
      },

      renderUser: function(user, editable) {
        var self = this;

        var li = new Element('li', { 'class': 'publisher' }).store('user', user);
        li.adopt(
          new Element('img', {
              src: user.profile_image_url || '/static/images/icons/default_profile_normal.png',
              events: { click: function() { self.services.userInfo.call(self, user.id); } }
          }),
          new Element('div', {
              'class': 'meta',
              html: user.display_name + ' <em>(Available ' + user.next_available + ')</em><br />' + intcomma(user.client_followers_count) + ' Followers | $' + intcomma(user.weekly_fee / 100) + ' per tweet'
          })
        );
        if (editable) {
          li.adopt(new Element('span', {"class": 'close', events: {
                  click: function() { self.removeUser(user.id); }
          }}));
        }

        return li;
      },

      renderUsersFragment: function() {
        var self = this;

        $('campaign_users_area').getElement('.empty').setStyle(
          'display',
          this.users['message_'+this.current_node].length ? 'none' : ''
        );

        $$('#message_'+this.current_node+' .assigned_publishers')[0].empty();

        if(this.users['message_'+this.current_node].length) {

          user_ids = [];

          this.users['message_' + this.current_node].each(function(user){
            var profile_pic = user.profile_image_url ? ('<img class="profile32" src="' + user.profile_image_url + '" alt="" />') : '<img class="profile32" src="/static/images/icons/default_profile_normal.png" alt="" />';

            new Element('li', {}).inject(
              $$('#message_'+self.current_node+' .assigned_publishers')[0]
            ).set('html',profile_pic);
          });

          $('publishers').value = user_ids.join(',');

          var step2 = $('campaign_users_area').getElement('button.add_more') !== null;
          var usersFragment = $('campaign_users_area').getElement('ul.user_portraits') ?
          $('campaign_users_area').getElement('ul.user_portraits') :
          new Element('ul', {'class': 'user_portraits'}).injectAfter(
            $('campaign_users_area').getElement('.empty')
          );
          usersFragment.empty();

          this.users['message_'+this.current_node].slice(0, 4).each(function(user) {
            usersFragment.adopt(self.renderUser.apply(self, [user, (step2 && (self.users['message_'+this.current_node].length !== 1)) || (!step2 && ($('campaign_form').getElement('input[name=publishers]') !== null))]));
          });

        } else {
          document.getElements('.campaign_users_area ul.user_portraits').dispose();
        }
        if(this.users['message_'+this.current_node].length >= 0){
          //$('campaign_users_area').getElement('#user_more').setStyle('display', this.users.length ? '' : 'none');
          $('campaign_users_area').getElement('.user_stat_tabs').setStyle('display', this.users['message_'+this.current_node].length ? '' : 'none');
        }
        if ($('campaign_users_area').getElement('button.add_more') && usersFragment) {
          $('campaign_users_area').getElement('button.add_more').inject($('user_more'));
        }

        this.renderStatTabs();
        return usersFragment;
      },

      renderTable: function(json, options) {
        var curlPage = document.location.pathname;
        json = json || this.loadedData;
        options = options || {};
        this.options.container = $('campaign_selector');
        if (json === null || json === undefined) { return; }

        var self = this;
        var is_overlay = (this.options.mode == 'overlay');
        if (curlPage == '/start-campaign/' || curlPage == '/start-campaign/2/'){
          var headers = [(is_overlay ? '+/-' : '<a href="#" class="add_all">Add All</a>'), 'Publisher Name', 'Followers', 'Price Per Pmessage'];}
        else {
          var headers = [(is_overlay ? '' : '<a href="#" class="add_all">Add All</a>'), 'Publisher Name', 'Followers', 'Price Per Message'];
        }
        var rels = ['', 'name', 'followers', 'price_per_tweet'];
        var is_editable = $chk($('campaign_form').getElement('input[name=publishers]'));

        if (!is_editable) {
          headers.shift();
          rels.shift();
        }
        var publishers;
        if (is_overlay) {
          headers.pop(); rels.pop();
          publishers = json.publishers.slice(json.args.offset, json.args.offset + json.args.limit);
        } else {
          publishers = json.publishers;
        }

        var thead = '<tr>' + headers.map(function(text, i){
          help_msg = self.help_messages[rels[i]] ? ' <img src="/static/images/icons/ico_help.png" alt="" class="tooltip" title="' + self.help_messages[rels[i]]  + '" />' : ''
          return '<th><span><em>' + text + help_msg + '</em></span></th>';
        }).join('') + '</tr>';
        var table = '<table id="publishers_table"><thead>' + thead;

        if(json.args.pub_name || json.args.category_1 || json.args.category_2 || json.args.price  || (json.args.num_followers && json.args.num_followers !=	"0-10000000")) {
          // Build String
          var filters = [];
          if(json.args.category_1) {
            filters.push('category "'+ jq('.category_1_'+json.args.category_1).html()+'"');
          }

          if(json.args.category_2) {
            filters.push('category "'+ jq('.category_2_'+json.args.category_2).html()+'"');
          }

          var pa = json.args.price.split('-');
          if(pa[0] != '0.0' || pa[1] != '100000.0') {
            filters.push('price "'+ jq('#price_sel_1 li.selected a').html() + "-" + jq('#price_sel_2 li.selected a').html() + '"');
          }

          var fa = json.args.num_followers.split('-');
          if(fa[0] != '0' || fa[1] != '10000000') {
            filters.push('number of followers "'+ jq('#followers_sel_1 li.selected a').html() +  "-" + jq('#followers_sel_2 li.selected a').html() + '"');
          }

          if(json.args.pub_name) {
            filters.push('name "'+ json.args.pub_name+'"');
          }
          if (filters.length > 0){
            table += '<tr class="search_notificiation"><th colspan="6"><div class="clearfix"><em>Filtering by '+filters.join(' and by ')+'</em></div></th></tr>';
          }
        }

        table += '</thead><tbody>';

        publishers.each(function(user, i) {
          //user.is_premium = (i % 2 == 0);
          var is_added = self.isUserAdded(user.id); /* user.id */
          var user_img = user.profile_image_url ? ('<img src="' + user.profile_image_url + '" alt="" />') : '<img src="/static/images/icons/default_profile_normal.png" alt="" />';
          if (curlPage == '/advertiser/start-campaign/' || curlPage == '/advertiser/start-campaign/2/'){
            var line_data = (!is_editable ? '' : (
                ['<td class="col_add">',
                  '<button type="button" name="',
                  (is_added ? 'remove' : (user.is_premium ? 'premium' : 'add')),
                  '" class=" ',
                  (is_added ? 'remove plain_button' : (user.is_premium ? 'greenButton' : 'add greenButton')),
                  '">',
                  (is_added ? (is_overlay ? 'x' : 'Remove') : 'Add'),
                  '</button>',
                  '</td>'].join(''))) +
            ['<td class="col_name">',
              '<div class="avatar">',
              user_img,
              '<em class="service ' + user.service + '"></em>',
              '</div>',
              '<span class="pubName">' + user.display_name + '</span></td>',
              '<td class="col_followers">',
              intcomma(user.client_followers_count),
              '</td>',
              '<td class="col_fee2">',
              ((isNaN(user.price_per_tweet)) ? user.price_per_tweet : ('$' + intcomma(user.price_per_tweet / 100))),
              '</td>'].join('');
          //(is_overlay ? '' : ('<td class="col_info">' + '<button type="button" name="info" class="button plain_button"><span>More Info &gt;</span></button>' + '</td>'))
          table += '<tr>' + line_data + '</tr>';
          } else {
            var line_data = (!is_editable ? '' : 
              (['<td class="col_add">',
                  '<button type="button" name="',
                  (is_added ? 'remove' : (user.is_premium ? 'premium' : 'add')),
                  '" class="button ',
                  (is_added ? 'remove plain_button' : (user.is_premium ? 'small_green' : 'add small_green')),
                  '"><span>',
                  (is_added ? (is_overlay ? '' : 'Remove') : 'Add'),
                  '<span></span></span></button>',
                  '</td>'].join(''))
            ) + [
              '<td class="col_name">',
              '<div class="avatar">',
              user_img,
              '<em class="service ' + user.service + '"></em>',
              '</div>',
              '<span class="pubName">',
              adly.utils.truncate(user.display_name, 25),
              '</span></td>',
              '<td class="col_followers">',
              intcomma(user.client_followers_count),
              '</td>',
              '<td class="col_fee2">',
              ((isNaN(user.price_per_tweet)) ? user.price_per_tweet : ('$' + intcomma(user.price_per_tweet / 100))),
              '</td>'].join('');
            //(is_overlay ? '' : ('<td class="col_info">' + '<button type="button" name="info" class="button plain_button"><span>More Info &gt;</span></button>' + '</td>'))].join('');
            table += '<tr>' + line_data + '</tr>';
          }
        });

        table += '</tbody></table>';
        var back_buffer = new Element('div', {html: table});


        if(back_buffer.getElements('.search_notificiation a').length) {
          back_buffer.getElement('.search_notificiation a').addEvent('click', function(){
            $$('#categories_sel, #categories_sel_1, #categories_sel_2, #num_followers_sel, #price_sel').each(function(el){
              var prefix = "Filter by ";
              if (el.id.slice(0,4) != '#cate') {
                prefix = '';
              }
              el.getElement('span').set("html","Filter by "+el.getElement('a').get('html'));
              if(el.getElement('li.selected')) {
                el.getElement('li.selected').removeClass('selected');
              }
            });
            $('search_box_form').getElement('.text').set('value','').fireEvent('blur');
            $('search_box_form').fireEvent('submit');
          });
        }

        if (options.can_has_sort) {
          var th_elems = back_buffer.getElements('table thead th');
          th_elems[rels.indexOf(json.args.order_by || 'followers')].addClass('order_by ' +  (json.args.order_asc ? 'order_asc' : 'order_desc'));

          rels.each(function(rel, i) {
            if (rel) {
              th_elems[i].store('rel', rel).addClass('action').addEvent('click', function(e) {
                this.toggleClass('order_asc').toggleClass('order_desc');
                self.services.getList.call(self, {
                    order_by: rel,
                    page: (self.options.container.getElement('ul.pagination') ? self.options.container.getElement('ul.pagination .selected').get('text').toInt() : 1)
                });
              });
            }
          });
        }

        back_buffer.getElements('a.add_all').addEvent('click', function(e) {
          e.stop();
          self.suspendRender();
          $('publishers_table').getElements('button.add').map(function(btn){ return btn.getParent('tr').retrieve('user').id; }).each(self.addUser.bind(self));
          self.forceUpdate();
        });

        new Tips(back_buffer.getElements('.tooltip').addEvent('click', Event.stop), {fixed: true, className: 'tip_wrap'});

        back_buffer.getElements('table tbody tr').each(function(tr, i) {
          tr.store('user', json.publishers[i]);
          tr.getElements('button').each(function(button) {
            var id = tr.retrieve('user').id;
            button.addEvent('click', function() {
              switch (this.get('name')) {
              case 'add':
                self.addUser(id); break;
              case 'remove':
                self.removeUser(id); break;
              case 'premium':
                if($('premium_bubble')) {
                  $('premium_bubble').destroy();
                }
                document.body.adopt( new Element('div', { id: 'premium_bubble', html:"<div class='pb_inner'><div class='pb_text'></div><a href='javascript:{}' class='pb_close'>Close</a></div>"}));
                $$('#premium_bubble .pb_close').addEvent('click',function(){
                  $('premium_bubble').destroy();
                });

                $('premium_bubble').setStyles({
                    display: 'block',
                    top: button.getPosition().y + (button.getSize().y / 2) - ($('premium_bubble').getSize().y/2),
                    left: button.getPosition().x + button.getSize().x + 2
                }).getElement('.pb_text').set('html', "Email <a href='mailto:sales@ad.ly'>sales@ad.ly</a> to create a campaign with "+tr.retrieve('user').display_name+" and to get pricing...");

                break;
              }
            });

            if(button.get('name') == 'info') {
              button.set('user',id);
              button.addEvent('click',function(e){
                self.services.userInfo.apply(self, [e.target, self]);
              });
              //CampaignManager.moreinfoTip.attach(button);
              //tr.getElements('.linked').each(function(a) {
              //});
              //CampaignManager.moreinfoTip.attach(tr.getElements('.linked'));
            }
          });
          tr.getElements('td.col_name span, td.col_name img').addClass('linked').set('user', tr.retrieve('user').id).each(function(el) {
            el.addEvent('click', function(e) {
              self.services.userInfo.apply(self, [e.target, self]);
            });
          });
        });
        adly.utils.bodyEvent('.col_name', 'click', function(e){
          var target = e.target || e.srcElement;
          target = $(target); //td
          target = target.getElement('img');
          self.services.userInfo.apply(self, [target, self]);
        });

        this.options.container.empty().adopt(back_buffer.childNodes);

        if (options.can_has_sort) {
          var sort_col = this.options.container.getElement('th.order_by');
          //sort_col.adopt( new Element('em', { styles: { width: sort_col.getElement('span').getSize().x } }));
        }

        this.renderPagination(json);

        if (is_overlay) { this.options.container.getElements('.pagination').setStyle('margin-top', 15 + (382 - $('femtocontent').getElement('table').getSize().y )); }

        this.reposition();
      },

      renderStatTabs: function() {
        jq.each(
          jq('#message_'+this.current_node+' .user_stat_tabs, #popup_content .user_stat_tabs'),
          jq.proxy(function(index, tabs) {
            // Set the messages stats bars
            var stats_cont = jq('li .value', tabs);
            stats_cont[0].innerHTML = '<strong>$ ' + intcomma(this.getTotalPrice()) + '</strong> Total Cost of Ad';
            stats_cont[1].innerHTML = '<strong>' + intcomma(this.users['message_'+this.current_node].length) + '</strong> Publisher' + ((this.users['message_'+this.current_node].length > 1) ? 's' : '');
            stats_cont[2].innerHTML = '<strong>' + intcomma(this.getTotalFollowers()) + '</strong> Followers Reach';
          }, this)
        );

        // Set the messages hidden input stats
        var tabRoot = '#message_' + this.current_node + ' .user_stat_tabs';
        jq('input.message_total_price', tabRoot).val(this.getTotalPrice());
        jq('input.message_total_publishers', tabRoot).val(this.users['message_' + this.current_node].length);
        jq('input.message_total_followers', tabRoot).val(this.getTotalFollowers());

        // Set this message's stats to show/hide depending on whether any pubs selected
        jq('.message_spend_label, .message_spend_field, .publisher_label', '#message_'+this.current_node).css(
          {'display': this.users['message_'+this.current_node].length ? 'block' : 'none'}
        );

        // Calculate stats totals for entire campaign
        var totalPrice = 0;
        var totalPublishers = 0;
        var totalFollowers = 0;
        for(var message_users in this.users) {
          totalPrice += this.getTotalPrice(message_users) * 100; // Ensures we're adding integers, avoiding floating point addition issues
          totalPublishers += this.users[message_users].length;
          totalFollowers += this.getTotalFollowers(message_users);
        }
        totalPrice /= 100; // Convert price back into dollars and cents

        if(this.message_id > 1){
          jq('#total_cost_container').css('display', 'inline')
          jq('#total_cost').text(intcomma(totalPrice))
        }else{
          jq('#total_cost_container').css('display', 'none')
        }
        /*
        if(totalPublishers) {
          // Show and set the total campaign stats bar
          var stats_cont = $('total_spend_holder').getElements('li .value');
          stats_cont[0].set('html', '<strong>$ ' + intcomma(totalPrice) + '</strong> Spend');
          stats_cont[1].set('html','<strong>' + intcomma(totalPublishers) + '</strong> Publisher' + ((totalPublishers > 1) ? 's' : ''));
          stats_cont[2].set('html','<strong>' + intcomma(totalFollowers) + '</strong> Followers Reach');
          $('total_spend_holder').setStyle('display','block');
          // Set the messages hidden input stats
          $('campaign_total_price').set('value', totalPrice);
          $('campaign_total_publishers').set('value', totalPublishers);
          $('campaign_total_followers').set('value', totalFollowers);
        } else {
          // Hide the total campaign stats bar (no pubs selected)
          $('total_spend_holder').setStyle('display','none');
          // Set the messages hidden input stats
          $('campaign_total_price').set('value', 0);
          $('campaign_total_publishers').set('value', 0);
          $('campaign_total_followers').set('value', 0);
        }
        */
      },

      renderPagination: function(json) {
        var self = this;
        var pages = Math.ceil(json.count / json.args.limit);
        var currentPage = (json.args.offset / json.args.limit) + 1;

        if (pages === 0) { return; }
        var is_overlay = (this.options.mode == 'overlay');

        var ul = new Element('ul', {'class': 'pagination'});
        if (currentPage > 1) {
          ul.adopt(new Element('li', {
                text: '< prev',
                'class': 'prev',
                events: {
                  click: function(e) {
                    e.stop();
                    if (!is_overlay) {
                      self.services.getList.call(self, {page: currentPage - 1});
                    } else {
                      self.loadedData.args.offset -= self.loadedData.args.limit;
                      self.renderTable();
                    }
                  }
                }
          }));
        }

        function _paginator(i) {
          if (i < pages) {
            if ((i < 3) || (i >= pages - 3) || (Math.abs(currentPage - (i + 1)) <= 1)) {
              ul.adopt(new Element('li', {
                    text: (i+1),
                    'class': ((i+1) == currentPage) ? 'selected' : '',
                    events: {
                      click: function(e) {
                        e.stop();
                        if (this.hasClass('selected')) { return; }
                        if (!is_overlay) {
                          self.services.getList.call(self, {page: i+1});
                        } else {
                          self.loadedData.args.offset = i * self.loadedData.args.limit;
                          self.renderTable();
                        }
                      }
                    }
              }));
              _paginator(i+1);
            } else {
              ul.adopt(new Element('li', {
                    text: '…',
                    'class': 'selected',
                    events: {
                      click: function(e) {
                        e.stop();
                        if (this.hasClass('selected')) { return; }
                        if (!is_overlay) {
                          self.services.getList.call(self, {page: i+1});
                        } else {
                          self.loadedData.args.offset = i * self.loadedData.args.limit;
                          self.renderTable();
                        }
                      }
                    }
              }));
              if (i < currentPage - 2)
                _paginator(currentPage - 2);
              else
                _paginator(pages - 3);
            }
          }
        }
        _paginator(0); // stupid closure

        if (currentPage < pages) {
          ul.adopt(
            new Element('li', { text: 'next >', 'class': 'next' }),
            new Element('li', { html: 'See next ' + self.loadedData.args.limit + ' results >>', 'class': 'next extra' })
          );

          ul.getElements('li.next').addEvent('click', function(e) {
            e.stop();
            if (!is_overlay) {
              self.services.getList.call(self, {page: currentPage + 1});
            } else {
              self.loadedData.args.offset += self.loadedData.args.limit;
              self.renderTable();
            }
          });
        }
        var div = new Element('div', {'id': 'table_cont'});
        div.adopt(ul);
        this.options.container.adopt(div);
        ul.getElements('li').addEvent('click', function(){
          self.options.container.scrollIntoView();
        });
      },

      services: {
        getList: function(options) {
          var options = options || {};
          var self = this;
          var _limit = 20;

          var container = options.container ? options.container : (this.options.container ? this.options.container : null);
          var on_success = options.on_success ? options.on_success : null;
          var selected_pubs = options.selected ? options.selected : null;
          var order_by = options.order_by ? options.order_by : null;
          var order_type = options.order_type ? options.order_type : null;
          var page = options.page ? options.page : null;
          var limit = options.limit ? options.limit : _limit;

          $$('.filter_applied ul').set('html','');

          var is_reset = true;

          var category_1 = null;
          if(document.getElement('#categories_sel_1 li.selected a')) {
            category_1 = document.getElement('#categories_sel_1 li.selected a').get('href').match(/#(\w+)/)[1];
          } else if(document.getElement('#categories_sel li.selected a')) {
            category_1 = document.getElement('#categories_sel li.selected a').get('href').match(/#(\w+)/)[1];
          }
          if(category_1 == 'all') {
            category_1 = null;
          }

          if(category_1 != null) {
            is_reset = false;
            var a = new Element('a', {href:'javascript:{}', html:document.getElement('#categories_sel_1 li.selected a').get('html')});
            a.addEvent('click', function(){
              var el = $('categories_sel_1');
              el.getElement('span').set("html","Filter by Category 1");
              if(el.getElement('li.selected')) {
                el.getElement('li.selected').removeClass('selected');
              }
              self.services.getList.apply(self);
            });
            var li = new Element('li');
            $$('.filter_applied ul').adopt(li.adopt(a));
          }

          var category_2 = null;
          if(document.getElement('#categories_sel_2 li.selected a')) {
            category_2 = document.getElement('#categories_sel_2 li.selected a').get('href').match(/#(\w+)/)[1];
          }

          if(category_2 == 'all') {
            category_2 = null;
          }

          if(category_2 != null) {
            is_reset = false;
            var a = new Element('a', {href:'javascript:{}', html:document.getElement('#categories_sel_2 li.selected a').get('html')});
            a.addEvent('click', function(){
              var el = $('categories_sel_2');
              el.getElement('span').set("html","Filter by Category 2");
              if(el.getElement('li.selected')) {
                el.getElement('li.selected').removeClass('selected');
              }
              self.services.getList.apply(self);
            });
            var li = new Element('li');
            $$('.filter_applied ul').adopt(li.adopt(a));
          }

          var min_price = null;
          if(jq('#price_sel_1 li.selected a').length) {
            min_price = jq('#price_sel_1 li.selected a').attr('href').match(/#(.+)/)[1];
          }
          var max_price = null;
          if(jq('#price_sel_2 li.selected a').length) {
            max_price = jq('#price_sel_2 li.selected a').attr('href').match(/#(.+)/)[1];
          }

          var min_followers = null;
          if(jq('#followers_sel_1 li.selected a').length) {
            min_followers = jq('#followers_sel_1 li.selected a').attr('href').match(/#(.+)/)[1];
          }
          var max_followers = null;
          if(jq('#followers_sel_2 li.selected a').length) {
            max_followers = jq('#followers_sel_2 li.selected a').attr('href').match(/#(.+)/)[1];
          }

          // if(min_followers != 10000 || max_followers != 1000000) {
          // is_reset = false;
          // var a = new Element('a', {href:'javascript:{}', html:$('slider_follower_label').get('html')+' followers'});
          // a.addEvent('click', function(){
          // $.price_slider.setMin(10000).setMax(1000000);
          // self.services.getList.apply(self);
          // });
          // var li = new Element('li');
          // $$('.filter_applied ul').adopt(li.adopt(a));

          // }

          // if(min_price != 10000 || max_price != 1000000) {
          // is_reset = false;
          // var a = new Element('a', {href:'javascript:{}', html:$('slider_price_label').get('html')+' dollars'});
          // a.addEvent('click', function(){
          // $.price_slider.setMin(10000).setMax(1000000);
          // self.services.getList.apply(self);
          // });
          // var li = new Element('li');
          // $$('.filter_applied ul').adopt(li.adopt(a));
          // }

          var q_name = null;
          if (document.getElement('#q_name')) {
            q_name = document.getElement('#q_name').get('value');
            q_name = (q_name != 'Enter name...') ? q_name : null;
          }
          if(q_name != null) {
            is_reset = false;

            var a = new Element('a', {href:'javascript:{}', html:'"'+q_name+'"'});
            a.addEvent('click', function(){
              var el = document.getElement('#q_name');
              el.set('value',el.get('rel'));
              self.services.getList.apply(self);
            });
            var li = new Element('li');
            $$('.filter_applied ul').adopt(li.adopt(a));
          }

          var q_talk = null;
          if (document.getElement('#q_talk')) {
            q_talk = document.getElement('#q_talk').get('value');
            q_talk = (q_talk != 'Enter keyword or phrase...') ? q_talk : null;
          }
          if(q_talk != null) {
            is_reset = false;

            var a = new Element('a', {href:'javascript:{}', html:'"'+q_talk+'"'});
            a.addEvent('click', function(){
              var el = document.getElement('#q_talk');
              el.set('value',el.get('rel'));
              self.services.getList.apply(self);
            });
            var li = new Element('li');
            $$('.filter_applied ul').adopt(li.adopt(a));
          }

          var q_location = null;
          if (document.getElement('#q_location')) {
            q_location = document.getElement('#q_location').get('value');
            q_location = (q_location != 'Enter city, state, or country...') ? q_location : null;
          }
          if(q_location != null) {
            is_reset = false;

            var a = new Element('a', {href:'javascript:{}', html:'"'+q_location+'"'});
            a.addEvent('click', function(){
              var el = document.getElement('#q_location');
              el.set('value',el.get('rel'));
              self.services.getList.apply(self);
            });
            var li = new Element('li');
            $$('.filter_applied ul').adopt(li.adopt(a));
          }

          if($('reset_all'))
          {
            if(is_reset) {
              $('reset_all').setStyle('display','none');
              $$('.filter_applied').setStyle('display','none');
            } else {
              $('reset_all').setStyle('display','block');
              $$('.filter_applied').setStyle('display','block');
            }
          }

          if (container) {
            container.addClass('working');
            order_by = order_by || (container.getElement('th.order_by') ? container.getElement('th.order_by').retrieve('rel') : null);
            order_type = order_type || (order_by ? (container.getElement('th.order_by.order_asc') ? 'asc' : 'desc' ) : null);
          }

          var params = {
            limit: limit,
            offset: page ? _limit * (page - 1) : null,
            order_by: order_by,
            order_type: order_type,
            category_1: category_1,
            category_2: ((category_2 != 'all') ? category_2 : null),
            min_followers: min_followers,
            max_followers: max_followers,
            min_price: min_price,
            max_price: max_price,
            q_name: q_name,
            q_talk: q_talk,
            q_location: q_location,
            selected: selected_pubs
          };

          if(this.only_added && this.users['message_'+this.current_node]) {
            var selected_users = [];
            $each(this.users['message_'+this.current_node], function(u){
              selected_users.push(u.id);
            });
            params.selected = selected_users.join(',');
          }

          new Request.JSON({
              url: this.options.services.getListURL + '&' + new Hash(params).toQueryString() + '&rand=' + (new Date().getTime()),
              onSuccess: function(response_json) {
                if(container){
                  container.removeClass('working');
                }
                self.loadedData = response_json;
                if (on_success) {
                  on_success(response_json);
                }
                else {
                  self.renderTable.apply(self, [response_json, {can_has_sort: true}]);
                }
              },
              onFailure: function(response_json){
                if(container){
                  container.removeClass('working');
                }
              }
          }).get();
        },

        userInfo: function(el, campaign) {
          var overlay, self = this, loaded_json = '';
          var is_editable = (document.getElements('#campaign_form input[name=publishers]').length > 0);
          if (!el.get('user')) {
            // Fix for Chrome targeting the wrong element
            el = el.getParent();
          }
          id = el.get('user');
          campaign = campaign || SponsorLab.campaign;
          var params = {
            ids: id,
            rand: (new Date().getTime())
          };

          var showInfo = function() {
            if (loaded_json != '') {
              var json = loaded_json[0];
              json.profile_image_url = json.profile_image_url || '/static/images/icons/default_profile_normal.png';
              var inner = ['about_publisher', 'categories', 'location', 'client_screen_name'].map(function(k) { return json[k] ? self.templateChunks[k] : ''; }).join('');
              var template = ['profile_image_url', 'display_name', 'client_followers_count'].map(function(k) { return json[k] ? self.templateChunks[k] : ''; }).join('');
              template += (((campaign && campaign.isUserAdded(id)) || (campaign === undefined) || !is_editable) ? '' : self.templateChunks.add_user) + (inner ? self.innerTemplate.substitute({info: inner}) : '');
              if (json.client_followers_count) { json.client_followers_count = intcomma(json.client_followers_count); }
              //$('moreinfo_body').set('html', self.infoTemplate.substitute({pub_data: template}).substitute(json));

              $('femtocontent').set('html', "<div class='overlay_wrapper'><a href='javascript:{}' class='close'>&nbsp;</a>"+self.infoTemplate.substitute({pub_data: template}).substitute(json)+"</div>");
              $('femtocontent').getElements('a.close').addEvent('click', function(e) { e.stop(); overlay.close.call(overlay); });
              $('femtocontent').getElements('button.small_green').addEvent('click', function() { campaign.addUser(id); overlay.close.call(overlay); });

              //overlay.reposition({y: $('femtocontent').getElement('div.overlay_wrapper').getScrollSize().y}, false);
            }
          };
          overlay = new Femtoverlay({size: {x: 720, y: 340}, onOpen: function(){
              new Request.JSON({
                  url: self.options.services.userInfoURL,
                  onSuccess: function(response_json) {
                    loaded_json = response_json;
                    showInfo();
                  }
              }).get(params);
          }});

          overlay.open();

        },

        showAllPublishers: function() {
          var self = this;
          new Femtoverlay({
              size: {x: 720, y: 400},
              onOpen: function() {
                $('femtocontent').setStyles({'background-image': 'none'});
                $('femtocontent').set('html', self.infoTemplate.substitute({pub_data: '<h1>Showing <span id="overlay_pub_count">{num}</span> Selected Publishers</h1>'.substitute({num: self.users['message_'+this.current_node].length})}));
                $('femtocontent').getElements('a.close').addEvent('click', function(e) { e.stop(); this.close(); }.bind(this));
                $('femtocontent').getElement('div.overlay_wrapper').removeClass('user_info').adopt(new Element('div', {'class': 'table_cont'}));
                var inner_campaign = new CampaignManager({
                    json: {
                      publishers: self.users,
                      args: {limit: 10, offset: 0},
                      count: self.users.length
                    },
                    container: $('femtocontent').getElement('div.table_cont'),
                    mode: 'overlay',
                    owner: this
                });
                this.reposition({y: size_y > this.overlay_min_y ? size_y : this.overlay_min_y}, false);
                $('femtocontent').getElement('div.table_cont').setStyle('height', $('femtocontent').getElement('div.table_cont').getSize().y - 6);
              }
          }).open();
        }
      }
  });

  //Added by Mindo
  var SignupOptions = {
    serviceTemplate: "/register-options",
    overlay: null,
    loadedContent: null,
    shouldRefresh: false,

    init: function(target) {
      this.overlay = new Femtoverlay({
        element: target,
        size: {x: 454, y: 198},
        onCreate: function() {
          this.shouldRefresh = false;
          this.loadIndex();
        }.bind(this),
        onOpen: this.loadContent.bind(this)
      });
    },

    loadIndex: function() {
      this.loadSection({ block: 'index' });
    },

    loadSection: function(options) {
      var self = this;

      new Request.HTML({
        url: this.serviceTemplate.substitute({block: options.block}),
        onSuccess: function(responseTree) {
          self.loadedContent = responseTree;
          self.shouldRefresh = self.shouldRefresh || $chk(this.getHeader('X-Splab-Refresh'));
          self.loadContent.call(self);
        }
      }).get();
    },

    loadContent: function() {
      var self = this;

      if ($('femtocontent') && this.loadedContent) {
        if ($type(this.loadedContent) == 'string') {
          $('femtocontent').empty().set('html', this.loadedContent);
        } else {
          $('femtocontent').empty().adopt(this.loadedContent);
        }

        SponsorLab.activate_dependables($('femtocontent').getElements('.dependable')).addEvent('dependable::update', function() { self.reposition.call(self, true); });
        // events
        this.reposition();
        $('femtocontent').getElements('a.close').addEvent('click', this.hide.bindWithEvent(this));
        $('femtocontent').getElements('ul.settings_sections li a').addEvent('click', function(e) {
          if (/#/.test(this.get('href'))) {
            e.stop();
            this.addClass('waiting');
            self.loadSection.call(self, { block: this.get('href').match(/#(\w+)/)[1] });
          }
        });
        $('femtocontent').getElements('a.go_back').addEvent('click', function(e) { e.stop(); self.loadIndex.call(self); });
        $('femtocontent').getElements('form').set('send', {
          onSuccess: function(responseHTML) {
            self.loadedContent = responseHTML;
            self.shouldRefresh = self.shouldRefresh || $chk(this.getHeader('X-Splab-Refresh'));
            self.loadContent.call(self);
          }
        }).addEvent('submit', function(e) { e.stop(); this.send(); });
      }
    },

    reposition: function(smooth) {
      this.overlay.reposition({y: $('femtocontent').getElement('div.overlay_wrapper').getScrollSize().y}, smooth);
    },

    hide: function(e) {
      if (e) { e.stop(); }
      if (this.shouldRefresh) {
        window.location.href = window.location.href;
      } else if (this.overlay) {
        this.overlay.close();
      }
    }
  };
  //eof

  var PreviewGen = new Class({
    // Sets up the message previews for campaign creation
    messageTemplates: {
      standard: '{message} (Ad)'
    },
    maxChars: 140,
    // TODO: we should be able to remove this regex completely
    cleansingFilter: /( (\(Sponsored via @Ad.ly\)))/gi,
    twitterSplitter: /(http:\/\/(www\.)?twitter.com\/)/gi ,
    urlSplitter: new RegExp(window.url_re, 'gi'),
    userSplitter: /@(\w+)/gi,
    timer: 0,
    sampleUrlMessage: '<strong>The URL you entered in the message box will be shortened<br/>and placed here when the tweet is sent. You can click on<br/>the link to go to the original URL.</strong>',

    initialize: function(message_area, shortener) {
      // Find the outer message wrapper and set everything up
      var message_wrapper = $$(message_area)[0];
      if (message_wrapper) {
        // Find and store required elements
        this.text_area = message_wrapper.getElement('textarea');
        this.preview_area = message_wrapper.getElement('.message-content');
        this.chars_left = message_wrapper.getElement('.chars_left');
        this.help_text = this.text_area.get('rel').trim();
        this.default_text = this.preview_area.get('text');

        // Set up events to handle updating on input
        this.text_area.addEvents({
          'keypress': this.keyEvent.bind(this),
          'keyup': this.keyEvent.bind(this)
        });
        var update_delay = function() {
          this.update.delay(5, this);
        }.bind(this);
        this.text_area.onpaste = update_delay;
        this.text_area.oninput = update_delay;

        // Hooks for choosing the shortener to use
        this.message_id = message_area.split('_')[1];
        this.shortener = shortener || 'bitly';
        jq('#adly_shortener_' + this.message_id).bind('click', {preview: this}, function(event){
          event.data.preview.shortener = 'jol.ly';
          event.data.preview.update();
        });
        jq('#bitly_shortener_' + this.message_id).bind('click', {preview: this}, function(event){
          event.data.preview.shortener = 'bit.ly';
          event.data.preview.update();
        });
        if (shortener == 'adly'){
          jq('#adly_shortener_' + this.message_id).click();
        }else{
          jq('#bitly_shortener_' + this.message_id).click();
        }

        // Perform initial preview update
        this.update();
      }
    },

    setupSampleUrls: function() {
      // Sets up sample bitly urls so that mouseover brings up a popup explainer box
      new Tips('.sample-url', {
        text: function() {
          return this.sampleUrlMessage;
        }.bind(this),
        fixed: true,
        className: 'tip_wrap tip-sample-url',
        offset: { x: -80, y: 20 }
      });
    },

    keyEvent: function() {
      // Handles update delays for key events
      if (this.timer) {
        $clear(this.timer);
        this.timer = 0;
      }
      this.timer = setTimeout(function(){ this.update() }.bind(this), 1);
    },

    update: function(options) {
      // Updates the message preview
      options = typeof(options) != 'undefined' ? options : {};
      update_options = {
        message_template: this.messageTemplates.standard
      }
      $extend(update_options, options);
      this.timer = 0;
      var template = update_options.message_template;
      var message_text = this.text_area.get('value').trim();
      if (message_text == this.help_text) {
        message_text = '';
      }

      if (message_text.length == 0) {
        // If message text is empty, set the explainer text
        this.preview_area.set('text', this.default_text).addClass('empty');
        this.chars_left.set('text', this.maxChars);
      }
      else {
        // If message text has been entered, update the preview
        // Clean up message text for display in preview
        // NOTE: The order of these replacements is VERY important!
        shortener = this.shortener;
        message_text = message_text
          .replace(this.cleansingFilter, '') // Remove clutter
          .replace(this.twitterSplitter, '@') // Replace twitter user links with @names
          .replace('<', '&lt;')
          .replace('>', '&gt;')
          .replace(this.urlSplitter, function(url) { // Replace URLs with fake bit.ly URLs
            var full_url = (url.indexOf('http://') == 0 || url.indexOf('https://') == 0) ? url : 'http://' + url;
            var short_url = '<a href="' + full_url + '" class="sample-url" target="_blank">http://' + shortener + '/sample</a>';
            return short_url;
          })
          .replace(/&(?![lg]t;)/g, '&amp;')
          .replace(this.userSplitter, function(url) { // Replace twitter @names with clickable links
            user_link = '<a href="http://twitter.com/' + url.replace('@', '') + '" target="_blank">' + url + '</a>';
            return user_link;
          });

        // Update the preview text
        this.preview_area.set('html', template.substitute({ message: message_text }));
        this.preview_area.removeClass('empty');

        // Update the char counter
        var chars = this.maxChars - this.preview_area.get('text').length;
        this.chars_left.set('text', chars).removeClass('warning').removeClass('depleting');
        if (chars >= 10 && chars < 20) {
          this.chars_left.addClass('warning');
        }
        else if (chars < 10) {
          this.chars_left.addClass('depleting');
        }

        // Add mouseover events to explain sample bitly urls
        this.setupSampleUrls();
      }
    }
  });

  // LoginHelp sets up a mouseover popup to offer login help in the header
  var LoginHelp = new Class({
    Implements: Options,
    options: {
      selector: '.login-help',
      buttonSelector: '.loginButton',
      popupSelector: '.popup',
      fadeDuration: 100
    },

    initialize: function(options) {
      this.setOptions(options);

      // Grab all login help instances and do initial setup
      this.helpWrappers = $(document.body).getElements(this.options.selector);
      this.helpWrappers.each(function(wrapper, index) {
        var button = this.getButton(wrapper);
        var popup = this.getPopup(wrapper);
        this.setBasicStyles(wrapper, button, popup);
        this.addMouseoverArea(wrapper, button);
        this.buildPopupEvents(wrapper);
        this.buildClickEvents(button);
      }.bind(this));
    },

    getButton: function(wrapper) {
      return wrapper.getChildren(this.options.buttonSelector)[0];
    },

    getPopup: function(wrapper) {
      return wrapper.getChildren(this.options.popupSelector)[0];
    },

    setBasicStyles: function(wrapper, button, popup) {
      // Set basic styles to allow popup to hover properly
      wrapper.setStyles({
        'display': 'inline',
        'position': 'relative'
      });
      button.setStyles({
        'display': 'inline',
        'position': 'relative',
        'z-index': 15
      });
      popup.setStyles({
        'display': 'block',
        'opacity': 0
      });
      var popupSize = popup.getSize();
      var buttonSize = button.getSize();
      this.popupTop = buttonSize.y + 5;
      this.popupLeft = (buttonSize.x / 2) - (popupSize.x / 2) - 33;
      popup.setStyles({
        'display': 'block',
        'opacity': 0,
        'left': this.popupLeft.toString() + 'px',
        'top': this.popupTop.toString() + 'px',
        'position': 'absolute',
        'z-index': 10,
        'width': '130px',
        'padding': '5px',
        'font-size': '12px',
        'text-align': 'center'
      });
      popup.getChildren().setStyles({
        'position': 'relative',
        'z-index': 15
      });
      var popupBackground = new Element('div', {
        'class': 'background',
        'styles': {
          'position': 'absolute',
          'top': 0,
          'left': 0,
          'width': '100%',
          'height': '100%',
          'z-index': 5,
          'background': '#FFFFFF url(/static/images/layout/input_back.png) repeat-x top left',
          'border': '1px solid #D6D6D6',
          '-moz-border-radius': '5px',
          '-webkit-border-radius': '5px'
        }
      });
      popupBackground.inject(popup, 'top');
    },

    addMouseoverArea: function(wrapper, button) {
      // Adds an invisible div covering the area between the button and the popup
      // so that the user can mouse from one to the other without triggering a
      // mouseleave event
      var size = wrapper.getSize();
      var area = new Element('div', {
        'class': 'mouseover-area',
        'styles': {
          'display': 'none',
          'position': 'absolute',
          'top': 0,
          'left': -20,
          'width': size.x + 40,
          'height': 40
        }
      });
      area.inject(wrapper);
    },

    buildPopupEvents: function(button, popup) {
      button.addEvents({

        'mouseenter': function(e) {
          wrapper = $(e.target).getParents(this.options.selector)[0];
          wrapper.getChildren('.mouseover-area').setStyle('display', 'block');
          var popup = this.getPopup(wrapper);
          var fadeIn = new Fx.Morph(popup, {
            duration: 100,
            transition: Fx.Transitions.Quad.easeOut
          });
          fadeIn.start({
            opacity: 1,
            top: (this.popupTop + 5).toString() + 'px'
          });
        }.bind(this),

        'mouseleave': function(e) {
          wrapper = $(e.target).getParents(this.options.selector)[0];
          wrapper.getChildren('.mouseover-area').setStyle('display', 'none');
          var popup = this.getPopup(wrapper);
          var fadeOut = new Fx.Morph(popup, {
            duration: 100,
            transition: Fx.Transitions.Quad.easeIn,
            onComplete: function(e) {
              popup.setStyle('top', (this.popupTop).toString() + 'px');
            }.bind(this)
          });
          fadeOut.start({
            opacity: 0,
            top: (this.popupTop + 10).toString() + 'px'
          });
          // TODO: Disable events for the duration of the transition to avoid accidental triggering
        }.bind(this)

      });
    },

    buildClickEvents: function(button) {
      button.addEvent('click', function() {
        document.location.href = ''
      })
    }
  });

  // PressTicker cycles through headlines on the home page
  var PressTicker = new Class({
    Implements: Options,
    options: {
      selector: '.ticker',
      animationDuration: 1000,
      pauseDuration: 6000
    },

    initialize: function(options) {
      this.setOptions(options);

      // Grab the ticker wrapper, set up, and start the animation
      this.ticker = $(document.body).getElements(this.options.selector)[0];
      if (this.ticker) {
        this.headlines = this.ticker.getElements('ul li');
        this.current_headline = this.headlines[0];
        this.setHeadlineStyles();
        this.changeHeadline.periodical(
          this.options.pauseDuration + this.options.animationDuration,
          this
        );
      }
    },

    setHeadlineStyles: function() {
      this.headlines.setStyles({
        'display': 'none',
        'opacity': 0
      });
      this.current_headline.setStyles({
        'display': 'inline',
        'opacity': 1
      });
    },

    changeHeadline: function() {
      // Fade out the current headline
      var fadeOut = new Fx.Morph(this.current_headline, {
        duration: this.options.animationDuration / 2,
        transition: Fx.Transitions.Quad.easeOut,
        onComplete: function() {
          this.current_headline.setStyle('display', 'none');
          // Grab the new headline
          this.current_headline = this.current_headline.getNext('li');
          if (!this.current_headline) {
            this.current_headline = this.headlines[0];
          }
          // Fade in the new headline
          this.current_headline.setStyle('display', 'inline');
          var fadeIn = new Fx.Morph(this.current_headline, {
            duration: this.options.animationDuration / 2,
            transition: Fx.Transitions.Quad.easeOut
          });
          fadeIn.start({opacity: 1});
        }.bind(this)
      });
      fadeOut.start({opacity: 0});
    }
  });

  Pager = new Class({
    Implements:[Options],
    initialize: function(options) {
      this.setOptions(options);
      this.initEvents();
    },

    initEvents: function(){
      this.url = this.options.url;
      this.url += (/\?/.test(this.url) ? '&' : '?') + 'page='
      var pages = $(this.options.id).getElements(this.options.selector);
      pages.each(function(element) {
        element.addEvent('click', this.page());
      }.bind(this));
    },

    page: function(){
      var self = this;
      return function(event){
        event.stop();
        new Request.HTML({
            evalScripts: false,
            url: self.url + event.target.getAttribute('page'),
            onSuccess: function(responseTree, responseElements, responseHtml) {
              $(self.options.id).empty().set('html', responseHtml);
              self.initEvents();
            }
        }).get();
      }
    }
  });

  TaskPoller = new Class({
    Implements:[Options],
    options: {
      timeout: 30,
      interval: 1,
      onSuccess: null,
      onFailure: null,
      onTimeout: null
    },
    initialize: function(options) {
      this.setOptions(options);
    },
    start: function(task_id) {
      var interval_id = 0;
      var startTime = new Date().getTime();
      var timeout = this.options.timeout * 1000;
      var options = this.options;
      interval_id = setInterval(function(){
        new Request.JSON({
            noCache: true,
            url: '/task/status/' + task_id + '/',
            onSuccess: function(response) {
              if (response.status){
                if (response.status == 'SUCCESS' && options.onSuccess){
                  options.onSuccess(response.result);
                }
                if (response.status == 'FAILURE' && options.onFailure){
                  options.onFailure(response.error);
                }
                clearInterval(interval_id);
              }
            }
        }).get();

        if (new Date().getTime() - startTime >= (timeout)){
          clearInterval(interval_id);
          if (options.onTimeout){
            options.onTimeout();
          }
        }
      }, this.options.interval * 1000);
    }
  });

  if (!window.console) { window.console = {log: function(){}, warn: function() {}, error: function(){}}; }

  window.addEvent('domready', function() { SponsorLab.init(); });
})();
adly = {};
adly.utils = {
  'includeScript': function(src){
    var script = document.createElement('script');
    script.type = 'text/javascript';
    script.src = src;
    document.head.appendChild(script);
  },

  // overwrites default object with another one
  // we use this for optional arguments
  // usage:
  // mergeObjects({'width':'10px'}, {'width':'20px', 'height':'30px'});
  // returns {'width':'10px', 'height':'30px'}
  mergeObjects: function(options, def){
    def = def || {};
    for(arg in options){
      def[arg] = options[arg];
    }
    return def;
  },

  //Usage:
  //arg1: element id
  //arg2: click/mousedown/mouseup/
  //arg3: callback handler
  bodyEvent: function(selector, eventType, handler, args, overwrite){
    if(typeof adly.eventsList == 'undefined'){
      adly.eventsList = {};
    }
    if(typeof adly.eventsHooked == 'undefined'){
      adly.eventsHooked = {};
    }
    var eL = adly.eventsList;
    var init = function(eventType){
      if(!document.body){
        setTimeout(function(){init(eventType);}, 500);
        return;
      }
      //console.log('init '+ selector + " " + eventType );
      if( !(eventType in adly.eventsHooked) ){
        //console.log('>new eventType: >'+ eventType+ '< set!');
        adly.eventsHooked[eventType] =
          $(document.body).addEvent(eventType, function(e){
            //e = e || event;
            //var target = e.target || e.srcElement;
            var target = e.target;
            if(!target){
              return;
            }
            if( !initHandlers(e, eventType, target) ){
              initHandlers(e, eventType, target.parentNode);
            }
          });
          //console.log(selector);
          //console.log(adly.eventsHooked[eventType]);
          //console.log(eventType);
      }
    };

    var initHandlers = function(e, eventType, target){
      var handler;
      if(!target){
        return handler;
      }
      if(target.id){
        handler = findHandler('#'+target.id, eventType);
        fireHandler(handler, target, e);
      }
      if(target.className){
        var eachClass = target.className.split(" ");
        for(var ii = 0, len = eachClass.length; ii < len; ii++){
          //console.log('init ' + eachClass[ii] + ' event: '+eventType);
          handler = findHandler('.'+eachClass[ii], eventType);
          fireHandler(handler, target, e);
        }
      }
      return handler;
    };

    var fireHandler = function(handler, context, evt){
      if(!handler){
        return;
      }
      function getArgs(handler){
        return [evt].concat(handler[1] || []);
      }
      if(typeof handler[0] == 'function'){
        handler[0].apply(context, getArgs(handler));
      }else if($type(handler[0]) == 'array'){
        for(var ii = 0, len = handler.length; ii < len; ii++){
          handler[ii][0].apply(context, getArgs(handler[ii]));
        }
      }
    };

    var findHandler = function(selector, eventType){
      //console.log('Find ' + selector + ' event: ' + eventType);
      //console.log(eL);
      if(selector in eL){
        //console.log(el[selector]);
        if(eventType in eL[selector]){
          //console.log(eL[selector][eventType]);
          return eL[selector][eventType];
        }
      }
    };

    var populate = function(selector, eventType, handler, args, overwrite){
      if(typeof eL[selector] == 'undefined'){
        eL[selector] = {};
      }
      if(eL[selector][eventType] && !overwrite){
        if($type(eL[selector][eventType][0]) == 'array'){
          eL[selector][eventType].push([handler, args]);
        }else{
          eL[selector][eventType] =
            [eL[selector][eventType], [handler, args]];
        }
      }else{
        eL[selector][eventType] = [handler, args];
      }
    };

    populate(selector, eventType, handler, args, overwrite);
    init(eventType);
  },
  capFirst: function(string) {
    return string.charAt(0).toUpperCase() + string.slice(1);
  },
  truncate: function(value, length){
    if (value && value.length > length){
      return value.substring(0, length - 3) + '...';
    }
    return value;
  },
  bootStrap: function(){
    if(jq.browser.msie){
      jq(document.body).addClass('ie');
    }
  }
};
window.addEvent('domready', function() { adly.utils.bootStrap(); });

// jQuery plugins
(function($) {
  
  /***
   * REVEALER PLUGIN -- slide in/out a confirmation box
   * expects to find three elements with the following classes inside the main element:
   *   .reveal_trigger : Clicking this opens up the content
   *   .reveal_content : This will be hidden/revealed (initializes as hidden)
   *   .reveal_hider : If included, this will cancel and rehide the content box
   ***/
  $.fn.revealer = function(options) {
    var settings = {
      init_hide_content: true,
      hide_trigger: true,
      reveal_trigger: null, // pass a node to explicitly choose a trigger
      reveal_content: null, // pass a node to explicitly choose content
      reveal_hider: null // pass a node to explicitly choose a hider
    };
    if (options) $.extend(settings, options);
    
    this.each(function() {
      var trigger = settings.reveal_trigger ? $(settings.reveal_trigger) : $(this).find('.reveal_trigger');
      var content = settings.reveal_content ? $(settings.reveal_content) : $(this).find('.reveal_content');
      var hider = settings.reveal_hider ? $(settings.reveal_hider) : $(this).find('.reveal_hider');
      // Initial styles
      trigger.css('outline', 'none');
      settings.init_hide_content ? content.hide() : content.show();
      // Set up triggers to show/hide content
      trigger.click(function() {
        content.slideDown(300);
        if (settings.hide_trigger) {
          trigger.animate({'opacity': 0}, 300, function() {
            trigger.css('cursor', 'default');
          });
        }
        return false;
      });
      hider.click(function() {
        content.slideUp(300);
        if (settings.hide_trigger) {
          trigger.animate({'opacity': 1}, 300, function() {
            trigger.css('cursor', 'pointer');
          });
        }
        return false;
      });
    });
    
    return this;
  };
  
})(jQuery);

