
/**
 * badge.js
 * This file creates the voting badge for a given article.
 * Usage:

&lt;script src="http://buzz.yahoo.com/build/badge.js"&gt;[publisher id]:[article id]&lt;/script&gt;

 * where [article id] is some identifying string, such as the canonical URL in
 * the feed, or a guid, or something.
 *
 * If there's no id specified, then the current location URL is used.
 * 
 **/

/* 

all hidden inputs are only attached to the form when the badge is clicked, to prevent someone from 
changing the target of the form to a hidden iframe or something and then submitting it programmatically.

*/

(function () {
	
	// Note: Make sure to update this when images are changed as part of front package!
	var default_host = 'http://buzz.yahoo.com';
	var loc = window.location.href;
	
	var ycs_prefix = /*STARTBUILDREPLACE YCS_PREFIX*/'http://l.yimg.com/ds'/*ENDBUILDREPLACE*/ + '/orion';
	var version = /*STARTBUILDREPLACE VERSION*/'1.0.0'/*ENDBUILDREPLACE*/;
	var image_host = ycs_prefix + '/' + version;
	
	// see if they've set any defaults on the window object.
	// Check these each time, and save individually for each badge, in case they get changed
	// before each script inclusion or something.
	var onLoad = window.yahooBuzzOnLoad || function () {};
	var _articleId = window.yahooBuzzArticleId;
	var _showBranding = window.yahooBuzzShowBranding;
	var _badgeType = window.yahooBuzzBadgeType;
	
	var init = function (el,article,badgeType,showBranding, badgeMarker) {
		
		// All hidden inputs should be created and appended on form submit
		// to reduce the amount of time that they sit around in the DOM,
		// and make it trickier to manipulate them.
		
		addInput({
			name:'from',
			value:'publisher'
		});
		
		addInput({
			name:'assettype',
			value:'article'
		});
		
		addInput({
			name:'publisherurn',
			value:article[0]
		});
		
		addInput({
			name:'guid',
			value:article[1]
		});
				
		addInput({
			name:'loc',
			value:loc
		});
		
		addInput({
			name:'votetype',
			value:1
		});
		createButton(el,badgeType,showBranding,host+'/buzz?publisherurn='+encodeURIComponent(article[0])+'&guid='+encodeURIComponent(article[1]), badgeMarker);
		
		onLoad.call(el);
	};
	
	var hiddenInputs = [];
	
	var create = function ( tagname, properties ) {
		var i = document.createElement(tagname);
		i.attachEventListener = nullFunction;
		i.removeEventListener = nullFunction;
		i.attachEvent = nullFunction;
		i.detatchEvent = nullFunction;
		for ( var p in properties ) {
			if ( p === 'style' ) {
				for ( var s in properties[p] ) {
					i.style[s] = properties[p][s];
				}
			} else {
				i[p] = properties[p];
			}
		}
		return i;
	};
	
	var createButton = function (form, type, showBranding, href, badgeMarker) {
		// TODO: nowrap
		var a, markup;
		var brandingSpan = '<span style="cursor:pointer;cursor:hand;color:#666;line-height:10px;display:block;margin-top:3px;font-size:10px;'+
			'font-family:Verdana,Tahoma,Arial,Helvetica,sans-serif;padding-right:5px;">on Yahoo!</span>';
		var attrs = {
			form : form,
			href : href,
			onclick : badgeClick
		};
		var style = {
			'textDecoration' : 'none',
			'width':'74px',
			'display' : 'block',
			'textAlign' : 'right'
		};
		switch ( type ) {
			case 'text':
				markup = '<span style="cursor:pointer;cursor:hand;position:relative;padding-left:20px;line-height:16px;">'+
					'<span style="cursor:pointer;cursor:hand;display:block;position:absolute;top:0;left:0;background:transparent url('+
					image_host+'/img/badge-logo.png) top left no-repeat;height:16px;width:16px;"></span>Yahoo! Buzz</span>';
				attrs.innerHTML = markup;
			break;
			case 'textbutton':
				markup = '<span style="cursor:pointer;cursor:hand;position:relative;left:-4px;padding-left:24px;font-size:80%;font-family:Verdana,Tahoma,Helvetica,Arial,sans-serif;display:block;line-height:22px;height:22px;color:#00c;background:url('+ image_host + '/img/badge-textbutton.png) left center no-repeat;">Buzz up!</span>';
				attrs.style = {
					target:'_new',
					width:'auto',
					position:'relative',
					left:'4px',
					display:'block',
					width:'80px',
					background:'url('+image_host+'/img/badge-textbutton.png) right center no-repeat'
				};
				attrs.innerHTML=markup;
			break;
			case 'logo':
				markup = '<span style="cursor:pointer;cursor:hand;position:relative;padding-left:20px;line-height:16px;">'+
					'<span style="cursor:pointer;cursor:hand;display:block;position:absolute;top:0;left:0;background:transparent url('+
					image_host+'/img/badge-logo.png) top left no-repeat;height:16px;width:16px;"></span></span>';
				attrs.innerHTML = markup;
			break;
			case 'small':
				markup = '<span style="cursor:pointer;cursor:hand;background:transparent url('+
					image_host+'/img/badge-small.png) top left no-repeat;display:block;height:0;padding-top:22px;width:74px;'+
					'text-indent:-999em;overflow:hidden">Buzz up!</span>';
				if ( showBranding ) {
					markup += brandingSpan;
				}
				attrs.style=style;
				attrs.innerHTML = markup;
			break;
			case 'large':
				markup = '<span style="cursor:pointer;cursor:hand;background:transparent url('+
					image_host+'/img/badge-large.png) top left no-repeat;display:block;height:0;padding-top:33px;'+
					'width:109px;text-indent:-999em;overflow:hidden">Buzz up!</span>';
				if (showBranding) {
					markup += brandingSpan;
				}
				attrs.style=style;
				style.width='109px';
				attrs.innerHTML = markup;
			break;
			case 'medium':
			default:
				markup = '<span style="cursor:pointer;cursor:hand;background:transparent url('+
					image_host+'/img/badge-medium.png) top left no-repeat;display:block;height:0;padding-top:27px;'+
					'width:91px;text-indent:-999em;overflow:hidden">Buzz up!</span>';
				if (showBranding) {
					markup += brandingSpan;
				}
				attrs.style=style;
				style.width='91px';
				attrs.innerHTML = markup;
			break;
		}
		var s = create('span',{id:form.id,className:form.className});
		s.appendChild(create('a',attrs));
		form.id = form.id+'-form';
		badgeMarker.parentNode.insertBefore(s,badgeMarker);
		badgeMarker.parentNode.removeChild(badgeMarker);
		// form.appendChild(a);
		cleanup();
	};
	
	
	var addInput = function (properties) {
		var i = create('input',properties);
		hiddenInputs.push(i);
	};
	
	// when the badge is clicked, all the hidden inputs are attached, and then
	// the form's onsubmit action is set to a null function, and then it is submitted.
	// this makes it tricky, but not impossible, to mess with the data.
	var badgeClick = function (e) {
		// alert('click!');
		
		e = e || window.event;
		var b = e.target||e.srcElement;
		while(b && b.tagName !== 'A') {
			b=b.parentNode;
		}
		if ( ! b ) {
			return true;
		}
		
		var f = b.form;
		// // console.log('formSubmit about to be called');
		formSubmit(f);
		// console.log('preventing default and returning false');
		if ( typeof(e.preventDefault) === 'function' ) {
			e.preventDefault();
		}
		e.returnValue = false;
		e.cancelBubble = true;
		e.stopPropagation && e.stopPropagation();
		return false;
	};
	var nullFunction = function (e) {
		return true;
	};
	var formSubmit = function (f) {
		// console.log('fs 1');
		if ( ! f ) {
			return true;
		}
		// console.log('fs 2');
		for ( var i = hiddenInputs.length - 1; i > -1; i -- ) {
			f.appendChild(hiddenInputs[i]);
		}
		// console.log('fs 3');
		f.onsubmit = nullFunction;
		document.body.appendChild(f);
		f.submit();
		// console.log('fs4');
		var inputs = f.getElementsByTagName('input');
		// console.log('fs4.1')
		for ( var i = 0, l = inputs.length; i < l; i ++ ) {
			// console.log('fs4.2 '+i);
			try {
				inputs[i].parentNode.removeChild(inputs[i]);
			} catch (ex) {
				continue;
			}
			// console.log('fs4.2 '+i+' done');
		}
		// console.log('fs5');
		f.parentNode.removeChild(f);
		// console.log('fs done');
	};
	
	
	var trueName = function () {
		var start = 'yahooBuzzBadge',
			t = start,
			i = 0,
			f;
		// if there's an element that another badge is using, then use the next one.
		while ( (f = document.getElementById(t)) && f.____yb == 1 || document.getElementById(t+'-form') ) {
			// console.log('cant use '+t+' because already in use by: ',f);
			t = start + '-' + i;
			i ++;
		}
		// mark it so that we know it's been claimed.
		if ( f ) {
			f.____yb = 1;
		}
		// console.log('trueName', t);
		return t;
	}();
	
	var scriptMarker = function () {
		// give it some random string
		var id = trueName;
		for (var i = 0; i < 5; i++) { 
		 	id += String.fromCharCode(Math.floor(Math.random() * 26) + 97); 
		}
		document.write('<span id="' + id + '" style="position:absolute;left:-999em;height:0;width:0;"></span>');
		return document.getElementById(id);
	}();
	scriptMarker.____yb = 1;
	
	// clean up what we put there.
	var cleanup;
	var host;
	
	window.setTimeout( function () {
		
		cleanup = function () {
			if ( scriptMarker && scriptMarker.parentNode ) {
				scriptMarker.parentNode.removeChild(scriptMarker);
			}
			element = null;
		};
		
		// find and save the script.
		// use scriptmarker as a reference point
		// Using document.write puts the generated content right *after* the script tag.
		// So, this script tag is the sibling right before the div.
		var script = function () {
			if ( !scriptMarker ) {
				return undefined;
			}
			var s = scriptMarker;
			
			while ( s && (!s.tagName || s.tagName !== 'SCRIPT') ) {
				// console.log(s);
				
				if ( s && s.previousSibling && s.previousSibling.tagName && s.previousSibling.childNodes.length ) {
					// console.log('set to previousSibling.lastChild');
					s = s.previousSibling.lastChild;
				} else if ( s === s.parentNode.firstChild ) {
					// console.log('set to parentNode');
					s = s.parentNode;
				} else {
					// console.log('set to previousSibling');
					s = s.previousSibling;
				}
			}
			// console.log(s);
			if ( !s ) {
				return undefined;
			}
			s.____yb = 1;
			return s;
		}();
		
		// if the script is being served from a yahoo site, then use the base url of the script
		// as the base url of the images.  Otherwise, use the default o url.
		host = (script && script.src) || '';
		if ( host.substr(0,1) === '/' ) {
			host = 'http://' + window.location.host;
		}
		host = host.replace(/^http:\/\/([^\/]+.yahoo.com)(:[0-9]+)?(\/.*)?/, 'http://$1$2');
		if ( ! host.match(/^http:\/\/([^\/]+.yahoo.com)(:[0-9]+)?$/) ) {
			host = default_host;
		}
		
		// if there's something in the script tag, then use that.
		// otherwise, use the current URL.
		var article = function () {
			var arg='';
			if ( _articleId && typeof(_articleId) === 'string' ) {
				arg = _articleId;
			} else if ( script && script.innerHTML && script.src ) {
				arg = script.innerHTML.replace(/[\n\r\s\t]+/g,' ').replace(/^\s+/,'').replace(/\s+$/,'');
			}
			arg = arg.split(':');
			return [ arg.shift(), arg.join(':') ];
		}();
		
		// figure out which kind of badge they want.
		// get it from the "badgetype" attribute on the script.
		var badgeType = function () {
			var bt;
			if ( _badgeType && typeof(_badgeType) === 'string' ) {
				bt = _badgeType;
			} else if ( script ) {
				bt = script.getAttribute('badgetype');
			}
			return bt || 'medium';
		}();
		
		var showBranding = function () {
			var sb;
			if ( _showBranding && typeof(_showBranding) !== 'undefined' ) {
				sb = _showBranding;
			} else if ( script ) {
				sb = script.getAttribute('showbranding');
			}
			if ( !isNaN(sb) ) {
				sb = (+sb);
			} else if (sb === 'false' || sb === 'no' || sb === 'off') {
				sb = false;
			}
			return !!sb;
		}();
		
		var badgeMarker = document.getElementById(trueName) || scriptMarker;
		badgeMarker.____yb = 1;
		
		var element = function () {
			if ( !badgeMarker ) {
				return undefined;
			}
			var f = create('form',{
				id : trueName+'-form',
				className : 'yahooBuzzBadge-form',
				action : host + '/vote/',
				method : 'post',
				target : '_new',
				____yb : 1,
				style : {
					position : 'absolute',
					height : '1px',
					width : '1px',
					visibility : 'hidden'
				}
			});
			badgeMarker.id = '';
			// badgeMarker.parentNode.insertBefore(f,badgeMarker);
			// badgeMarker.parentNode.removeChild(badgeMarker);
			// console.log('form: ',trueName, f.____yb, f);
			return f;
		}();
		
		
		init(element, article, badgeType, showBranding, badgeMarker);
		
	}, 0 ); // end settimeout
	
	
})();
// window.onbeforeunload = function () {return 'bar';}
