// blogdowntown js code

var blogdowntown = {}

// - - - Comment Preview - - - //

blogdowntown.CommentPreview = Class.create()

blogdowntown.CommentPreview.prototype = {
	DefaultOptions : {
		textarea	: 'commentbox',
		preview		: 'preview'
	},

	initialize : function (options) {
		this.options = Object.extend(
			Object.extend({},this.DefaultOptions), options || {}
		);

		this.textarea = $(this.options.textarea)
		this.preview = $(this.options.preview)

		this.showdown = new Showdown.converter()

		// attach to changes in the commentbox
		this.observer = new Form.Element.Observer(
			this.textarea,
			0.5,
			this.updatePreview.bind(this)
		)
	},

	updatePreview : function () {
		Element.update(
			this.preview,
			this.showdown.makeHtml(Form.Element.getValue(this.textarea))
		)
	}	
}

// - - - Count Form Field Content Length - - - //

blogdowntown.LiveCount = Class.create({
    DefaultOptions : {
        interval : 10
	},
	
	initialize : function (elements,options) {
		this.options = Object.extend(
			Object.extend({},this.DefaultOptions), options || {}
		);
		
	    (elements||[]).each(function(e) {
	        if ( $(e[0]) && $(e[1]) ) {
	            setInterval(function() {
	                $(e[1]).innerHTML = $(e[0]).value.length
	            },e[2] || this.options.interval)
	        }
	    }.bind(this))
	}
})

// - - - Comment Code Generator - - - //

blogdowntown.CommentCode = Class.create()

blogdowntown.CommentCode.prototype = {
	DefaultOptions : {
		codeinput	: 'commentcode',
		waittext 	: 'Please Wait'
	},
	initialize : function (options) {
		this.options = Object.extend(
			Object.extend({},this.DefaultOptions), options || {}
		);

		this.clickedButton = null

		this.input = $(this.options.codeinput)
		this.form = this.input.form

		// get all the submit buttons
		this.buttons = Form.getInputs(this.form,'submit')
		
		this.buttontext = {};

		// attach trackers to each of the submit buttons
		this.buttons.each(function(el){
			el.onclick = this._clickedButton.bind(this,el.name)
			this.buttontext[ el ] = el.value
		}.bind(this))

		// attach ourself to the form
		this.oldsubmit = this.form.onsubmit.bind(this.form)
		this.form.onsubmit = this.submit.bind(this)
	},
	_clickedButton : function(name) {
		this.clickedButton = name
	},
	
	submit : function() {
		/* if (!this.clickedButton || this.clickedButton != 'post') {
			return true
		} */
	
		// -- disable the form -- //
		Form.disable(this.form)

		// -- set our waiting message -- //
		this.buttons.each(function(el){
			el.value = this.options.waittext
		}.bind(this))

		// -- send off our code request -- //

		var req = new Ajax.Request(
			this.options.url,
			{
				method: 'get',
				onComplete : this._insertCode.bind(this)
			}
		)

		// -- return -- //

		return false
	},

	_insertCode : function (req) {
		// -- place code into the form -- //

		this.input.value = req.responseText

		// -- re-enable the form -- //
		Form.enable(this.form)
		
		// -- replace text in buttons -- //
		this.buttons.each(function(el){
			el.value = "Sending"
		}.bind(this))
		
		// -- fire the submit -- //

		if ( this.oldsubmit ) {
			this.oldsubmit()
		} else {
			this.form.submit()
		}		
	}
}

//----------

blogdowntown.StoryMap = Class.create()
blogdowntown.StoryMap.prototype = {
    DefaultOptions : {
        div : "storymap",
        width : 492,
        height : 240
	},
    initialize : function(story,options) {
        this.options = Object.extend(
			Object.extend({},this.DefaultOptions), options || {}
		);

		// find our div		
		if ( this.div = $( this.options.div ) ) {
		    // set up the map
		    //this.map = new google.maps.Map2(this.div,{size: new google.maps.Size(this.options.width,this.options.height)});
		    
		    var d = Element.getDimensions( this.div )
		    this.map = new google.maps.Map2(this.div,{size: new google.maps.Size(d.width,d.height)});
		    
    	    this.map.addControl(new google.maps.SmallMapControl());

            this.map.removeMapType(G_SATELLITE_MAP)
            this.map.addMapType(G_PHYSICAL_MAP)
            this.map.addControl(new google.maps.MapTypeControl());
            
            //this.map.addControl(new google.maps.OverviewMapControl)
            
            this.map.setMapType(G_PHYSICAL_MAP)
    	    
    	    var marker = new google.maps.Marker(new google.maps.LatLng(story.lat,story.lng), {draggable:false})
    	    this.map.setCenter(marker.getLatLng(), 14);
    	    this.map.addOverlay(marker)
		}
    }
}

//----------

blogdowntown.GeoSearch = Class.create()
blogdowntown.GeoSearch.prototype = {
    DefaultOptions : {
        div : "map",
        width : 492,
        height : 240,
        zoom : 14,
        lat : 34.048353,
        lng : -118.25292,
        search_button : "geosearch_button",
        results : "results",
        ctlClass : 'active',
        ctl30days : 'ctl30days',
        ctl6mons : 'ctl6mons',
        ctlNoLimit : 'ctlNoLimit'
        
	},
    initialize : function(story,options) {
        this.options = Object.extend(
			Object.extend({},this.DefaultOptions), options || {}
		);

		// find our div		
		if ( this.div = $( this.options.div ) ) {
		    // set up the map
		    this.map = new google.maps.Map2(this.div,{size: new google.maps.Size(this.options.width,this.options.height)});
    	    this.map.addControl(new google.maps.SmallMapControl());

            this.map.removeMapType(G_SATELLITE_MAP)
            this.map.addMapType(G_PHYSICAL_MAP)
            this.map.addControl(new google.maps.MapTypeControl());
            
            //this.map.addControl(new google.maps.OverviewMapControl)
            
            this.map.setMapType(G_PHYSICAL_MAP)
            
            this.lat = this.options.lat
            this.lng = this.options.lng
    	    
    	    var marker = new google.maps.Marker(new google.maps.LatLng(this.lat,this.lng), {draggable:true})
    	    this.map.setCenter(marker.getLatLng(), this.options.zoom);
    	    this.map.addOverlay(marker)
    	    
    	    this.marker = marker
    	    
            // find our controls
    	    this.ctl30days = $( this.options.ctl30days )
    	    this.ctl6mons = $( this.options.ctl6mons )
    	    this.ctlNoLimit = $( this.options.ctlNoLimit )
    	        	    
    	    // activate the move control
            this._activateControl(this.ctlNoLimit)

            // attach control listeners
            this.ctl30days.observe('click',this._activateControl.bind(this,this.ctl30days,"30days"))
            this.ctl6mons.observe('click',this._activateControl.bind(this,this.ctl30days,"6mons"))
            this.ctlNoLimit.observe('click',this._activateControl.bind(this,this.ctl30days,"none"))
    	    
    	    // add a drag listener to the marker
    	    this.dragL = google.maps.Event.addListener(marker,"dragend", this._handleMarkerDrag.bind(this))
    	    
    	    if ( this.sbutton = $( this.options.search_button ) ) {
    	        // attach a listener to the search button
    	        this.sbutton.observe('click',this.search.bind(this))
    	    }
		}
    },
    
    //----------
    
    _activateControl : function (ctl,value) {
      ["ctl30days","ctl6mons","ctlNoLimit"].each(function(i) { 
        this[ i ].removeClassName(this.options.ctlClass)  
      }.bind(this))
      
      if (ctl) {
        ctl.addClassName( this.options.ctlClass )
        this._ctlValue = value
      }
    },
    
    //----------
    
    _handleMarkerDrag : function() {
        this.lat = this.marker.getLatLng().lat()
        this.lng = this.marker.getLatLng().lng()
    },
    
    //----------
    
    //----------
    
    search : function () {
        //alert('fire off search at ' + [this.lat,this.lng].join(','))
        
        // fire off search request
        new Ajax.Updater(
            this.options.results,
            window.location.href,
            { 
                parameters : { lat : this.lat , lng : this.lng },
                onComplete : this._scrollToResults.bind(this)
            }
        )
    },
    
    //----------
    
    _scrollToResults : function() {
        //alert("TODO: scroll to results")
        Element.scrollTo(this.sbutton)
    }
}


//----------

blogdowntown.NewsroomStoryFX = Class.create()
blogdowntown.NewsroomStoryFX.prototype = {
    initialize : function (id) {
        // save our story id
        this.story = id
        
        var vAcc = new accordion('accordion')
        vAcc.activate($$('#accordion .accordion_toggle')[0]);

        this.activatePhotoDrag()
    },
    activatePhotoDrag : function () {
        // set up sortable on the story photos
        var sort = Sortable.create("story_photos",{
            tag : "div",
            onUpdate : this._updatePhotoOrder.bind(this)
        })        
    },
    _updatePhotoOrder : function (c) {
        new Ajax.Request(
            "/newsroom/story/"+this.story+"/photos/order",{
            parameters : Sortable.serialize(c)
        })
    }
}

//----------

blogdowntown.TipFX = Class.create();
blogdowntown.TipFX.prototype = {
    DefaultOptions : {
        show_ctl: 'tip_form_show',
        hide_ctl: 'tip_form_cancel',
        
        opener: 'tip_opener',
        widget: 'tip_form'
    },
    
    initialize : function(options) {
        this.options = Object.extend(
			Object.extend({},this.DefaultOptions), options || {}
		);
		
		this.show = $( this.options.show_ctl )
		this.hide = $( this.options.hide_ctl )
		
		this.opener = $( this.options.opener )
		this.widget = $( this.options.widget )
		
		if ( this.show && this.hide ) {
		    this.showHandler = this._handleShow.bind(this)
		    this.hideHandler = this._handleHide.bind(this)
		    
		    // attach listener to both to start
		    this.show.observe('click',this.showHandler)
		    this.hide.observe('click',this.hideHandler)
		}
    },
    
    _handleShow : function() {
        // detach show listener to prevent double clicks
        this.show.stopObserving('click',this.showHandler)
        
        new Effect.BlindUp(this.opener,{
            afterFinish : function () {
                new Effect.Grow(this.widget,{ afterFinish : function () {
                    this.show.observe('click',this.showHandler)
                }.bind(this),direction: "top-left"});                
            }.bind(this)
        })
        
    },
    
    _handleHide : function() {
        this.hide.stopObserving('click',this.hideHandler)
        
        new Effect.BlindUp(this.widget,{ afterFinish : function () {
            new Effect.BlindDown(this.opener,{ afterFinish : function () {
                this.hide.observe('click',this.hideHandler)
            }.bind(this)})            
        }.bind(this)});
    }
}

//----------

// ActiveContent handles the Active Stories / Recent Comments widget
blogdowntown.ActiveContent = Class.create();
blogdowntown.ActiveContent.prototype = {
    DefaultOptions : {
        tabs : ['rc_stories','rc_comments'],
        dvalue : 1,
        cookie : "blogdowntown_activeContent"
	},

	initialize : function (options) {
		this.options = Object.extend(
			Object.extend({},this.DefaultOptions), options || {}
		);
		
		this.options.tabs.each(function(id,idx) {
		    Event.observe(id+"_c","click",this._clickedTab.bind(this,id,idx))
		}.bind(this))
		
		// set one visible
		
		var init = Cookie.get(this.options.cookie) || this.options.dvalue
		this._clickedTab(this.options.tabs[init-1],init-1)
	},
	
	_clickedTab : function (tab,idx) {
	    // turn everyone off
	    this.options.tabs.each(function(id) {
	        $(id).hide()
	        $(id+"_c").removeClassName('active')
	    })
	    	    
	    // turn ours on
	    $(tab).show()
	    $(tab+"_c").addClassName('active')
	    
	    // set a cookie
	    Cookie.set(this.options.cookie,idx+1,86400)
	}
}

//----------

blogdowntown.DiffText = Class.create()
blogdowntown.DiffText.prototype = {
    initialize : function() {
        return true
    },
    
    diff : function(o,n) {
        o = o.replace(/\s+$/, '');
        n = n.replace(/\s+$/, '');

        var out = this._diff(o == "" ? [] : o.split(/\s+/), n == "" ? [] : n.split(/\s+/) );
        var str = "";

        var oSpace = o.match(/\s+/g);
        if (oSpace == null) {
          oSpace = ["\n"];
        } else {
          oSpace.push("\n");
        }
        var nSpace = n.match(/\s+/g);
        if (nSpace == null) {
          nSpace = ["\n"];
        } else {
          nSpace.push("\n");
        }

        if (out.n.length == 0) {
            for (var i = 0; i < out.o.length; i++) {
              str += '<del>' + this._escape(out.o[i]) + oSpace[i] + "</del>";
            }
        } else {
          if (out.n[0].text == null) {
            for (n = 0; n < out.o.length && out.o[n].text == null; n++) {
              str += '<del>' + this._escape(out.o[n]) + oSpace[n] + "</del>";
            }
          }

          for ( var i = 0; i < out.n.length; i++ ) {
            if (out.n[i].text == null) {
              str += '<ins>' + this._escape(out.n[i]) + nSpace[i] + "</ins>";
            } else {
              var pre = "";

              for (n = out.n[i].row + 1; n < out.o.length && out.o[n].text == null; n++ ) {
                pre += '<del>' + this._escape(out.o[n]) + oSpace[n] + "</del>";
              }
              str += " " + out.n[i].text + nSpace[i] + pre;
            }
          }
        }

        return str;  
    },
    
    //----------
    
    _escape : function(s) {
        var n = s;
        n = n.replace(/&/g, "&amp;");
        n = n.replace(/</g, "&lt;");
        n = n.replace(/>/g, "&gt;");
        n = n.replace(/"/g, "&quot;");

        return n;
    },
    
    //----------
    
    _diff : function( o, n ) {
      var ns = new Object();
      var os = new Object();

      for ( var i = 0; i < n.length; i++ ) {
        if ( ns[ n[i] ] == null )
          ns[ n[i] ] = { rows: new Array(), o: null };
        ns[ n[i] ].rows.push( i );
      }

      for ( var i = 0; i < o.length; i++ ) {
        if ( os[ o[i] ] == null )
          os[ o[i] ] = { rows: new Array(), n: null };
        os[ o[i] ].rows.push( i );
      }

      for ( var i in ns ) {
        if ( ns[i].rows.length == 1 && typeof(os[i]) != "undefined" && os[i].rows.length == 1 ) {
          n[ ns[i].rows[0] ] = { text: n[ ns[i].rows[0] ], row: os[i].rows[0] };
          o[ os[i].rows[0] ] = { text: o[ os[i].rows[0] ], row: ns[i].rows[0] };
        }
      }

      for ( var i = 0; i < n.length - 1; i++ ) {
        if ( n[i].text != null && n[i+1].text == null && n[i].row + 1 < o.length && o[ n[i].row + 1 ].text == null && 
             n[i+1] == o[ n[i].row + 1 ] ) {
          n[i+1] = { text: n[i+1], row: n[i].row + 1 };
          o[n[i].row+1] = { text: o[n[i].row+1], row: i + 1 };
        }
      }

      for ( var i = n.length - 1; i > 0; i-- ) {
        if ( n[i].text != null && n[i-1].text == null && n[i].row > 0 && o[ n[i].row - 1 ].text == null && 
             n[i-1] == o[ n[i].row - 1 ] ) {
          n[i-1] = { text: n[i-1], row: n[i].row - 1 };
          o[n[i].row-1] = { text: o[n[i].row-1], row: i - 1 };
        }
      }

      return { o: o, n: n };
    }
}

//----------

blogdowntown.UserPhotos = Class.create()
blogdowntown.UserPhotos.prototype = {
    DefaultOptions : {
        finder: '#user_photos_thumbs img',
        load : 'user_photos_load',
        pop : 'user_photos_pop',
        
        nprev: 'user_photos_prev',
        nnext: 'user_photos_next',
        nclick: 'user_photos_click'
    },
    
    initialize : function(options) {
        this.options = Object.extend(
			Object.extend({},this.DefaultOptions), options || {}
		);
		
		this.load = $( this.options.load )
		
		this.count = 0
		this.current = null
		
		this.handlers = []
		
		var i = 0
		
		// attach to each image in the thumbs div
		$$(this.options.finder).each(function(img) {
		    //console.info('got img: ',img)
		    
		    var handler = this._handleImgClick.bind(this,img,img.parentNode.href,i)
		    img.observe('click',handler)
		    
		    this.handlers[i] = handler
		    
		    // update counters
		    this.count++
		    i++
		    
		    // replace the normal href
			img.parentNode.href = 'javascript:void(0)'
		}.bind(this))
	},
	
	_handleImgClick : function(img,href,i) {
	    //console.warn('got click for ',i,href)
	    
	    this.current = i
	    
	    new Ajax.Updater(
			this.load,
			href,
			{
			    method : "GET",
				asynchronous : true,
				evalScripts : true,
				onComplete : function(req) {
				    this._activateNavLinks()
					RedBox.addHiddenContent(this.load)
					
					// logging
					//Mint.TT.behavior.record("galleryView",href)
					gUrl = href.match(/(\/[^\/]+)$/)
					
					if (gUrl) {
					    //console.warn('logging for ' + window.location.pathname + gUrl[1])
    					pageTracker._trackPageview(window.location.pathname + gUrl[1])					    
					}
				}.bind(this),
				onLoading : function() {
					RedBox.loading()
				}
			}
		)
	},
	
	_activateNavLinks : function() {
	    var nprev = $(this.options.nprev)
	    var nnext = $(this.options.nnext)
	    var nclick = $(this.options.nclick)
	    
	    if ( nprev && this.current > 0 ) {
	        // add prev link
	        //console.info("adding prev link")
	        nprev.observe("click",this._handlePrevClick.bind(this))
	        nprev.show()
	    } else {
	        $(this.options.nprev).hide()	        
	    }
	    
	    if ( nnext && this.current < (this.count-1) ) {
	        // add next link
	        //console.info("adding next link")
	        nnext.observe("click",this._handleNextClick.bind(this))
	        nnext.show()
	        
	        // also make _click go next
	        if (nclick) {
	            nclick.observe("click",this._handleNextClick.bind(this))
	        }
	    } else {
	        $(this.options.nnext).hide()
	        
	        // make _click close the gallery
	        if (nclick) {
	            nclick.observe("click",RedBox.close.bind(this))
	        }	        
	    }
	},
	
	_handlePrevClick : function() {
	    // run the handler for current - 1
	    if ( this.current > 0 ) {
	        this.handlers[ this.current - 1 ]()
	    }
	},
	
    _handleNextClick : function() {
        // run the handler for current + 1
        if ( this.current < (this.count - 1) ) {
	        this.handlers[ this.current + 1 ]()
	    }
    }
	
}

// cookie code from prototype-tidbits
// http://livepipe.net/projects/prototype_tidbits/

/**
 * Tidbit : Cookie
 */

var Cookie = {
	set: function(name,value,seconds){
		if(seconds){
			d = new Date();
			d.setTime(d.getTime() + (seconds * 1000));
			expiry = '; expires=' + d.toGMTString();
		}else
			expiry = '';
		document.cookie = name + "=" + value + expiry + "; path=/";
	},
	get: function(name){
		nameEQ = name + "=";
		ca = document.cookie.split(';');
		for(i = 0; i < ca.length; i++){
			c = ca[i];
			while(c.charAt(0) == ' ')
				c = c.substring(1,c.length);
			if(c.indexOf(nameEQ) == 0)
				return c.substring(nameEQ.length,c.length);
		}
		return null
	},
	unset: function(name){
		Cookie.set(name,'',-1);
	}
}

1;

