<commit_before>/**

Donations welcome:
	BTC: 122MeuyZpYz4GSHNrF98e6dnQCXZfHJeGS
	LTC: LY1L6M6yG26b4sRkLv4BbkmHhPn8GR5fFm
		~ Thank you!

------------

MIT License (MIT)

Copyright (c) 2013 http://coinwidget.com/
Copyright (c) 2013 http://scotty.cc/

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

*/

if (typeof CoinWidgetComCounter != 'number')
var CoinWidgetComCounter = 0;

if (typeof CoinWidgetCom != 'object')
var CoinWidgetCom = {
	source: 'http://coinwidget.com/widget/'
	, config: []
	, go :function(config) {
		config = CoinWidgetCom.validate(config);
		CoinWidgetCom.config[CoinWidgetComCounter] = config;
		CoinWidgetCom.loader.jquery();
		document.write('');
		CoinWidgetComCounter++;
	}
	, validate: function(config) {
		var $accepted = [];

		$accepted['currencies'] = ['bitcoin','litecoin'];
		$accepted['counters'] = ['count','amount','hide'];
		$accepted['alignment'] = ['al','ac','ar','bl','bc','br'];

		if (!config.currency || !CoinWidgetCom.in_array(config.currency,$accepted['currencies']))
			config.currency = 'bitcoin';

		if (!config.counter || !CoinWidgetCom.in_array(config.counter,$accepted['counters']))
			config.counter = 'count';

		if (!config.alignment || !CoinWidgetCom.in_array(config.alignment,$accepted['alignment']))
			config.alignment = 'bl';

		if (typeof config.qrcode != 'boolean')
			config.qrcode = true;

		if (typeof config.auto_show != 'boolean')
			config.auto_show = false;

		if (!config.wallet_address)
			config.wallet_address = 'My '+ config.currency +' wallet_address is missing!';

		if (!config.lbl_button)
			config.lbl_button = 'Donate';

		if (!config.lbl_address)
			config.lbl_address = 'My Bitcoin Address:';

		if (!config.lbl_count)
			config.lbl_count = 'Donation';

		if (!config.lbl_amount)
			config.lbl_amount = 'BTC';

		if (typeof config.decimals != 'number' || config.decimals < 0 || config.decimals > 10)
			config.decimals = 4;

		return config;
	}
	, init: function(){
		CoinWidgetCom.loader.stylesheet();
		$(window).resize(function(){
			CoinWidgetCom.window_resize();
		});
		setTimeout(function(){
			/* this delayed start gives the page enough time to
			   render multiple widgets before pinging for counts.
			*/
			CoinWidgetCom.build();
		},300);
	}
	, build: function(){
		$containers = $("span[data-coinwidget-instance]");
		$containers.each(function(i,v){
			$config = CoinWidgetCom.config[$(this).attr('data-coinwidget-instance')];
			$counter = $config.counter == 'hide'?'':('');
			$button = ''+$config.lbl_button+''+$counter;
			$(this).html($button);
			$(this).find('> a').unbind('click').click(function(e){
				e.preventDefault();
				CoinWidgetCom.show(this);
			});
		});
		CoinWidgetCom.counters();
	}
	, window_resize: function(){
		$.each(CoinWidgetCom.config,function(i,v){
			CoinWidgetCom.window_position(i);
		});
	}
	, window_position: function($instance){
		$config = CoinWidgetCom.config[$instance];
		coin_window = "#COINWIDGETCOM_WINDOW_"+$instance;

		if ($(coin_window).is(':visible')) {
			obj = "span[data-coinwidget-instance='"+$instance+"'] > a";
			/* 	to make alignment relative to the full width of the container instead
			of just the button change this occurence of $(obj) to $(obj).parent(),
			do the same for the occurences within the switch statement. */
			$pos = $(obj).offset();
			switch ($config.alignment) {
				default:
				case 'al': /* above left */
					$top = $pos.top - $(coin_window).outerHeight() - 10;
					$left = $pos.left;
					break;
				case 'ac': /* above center */
					$top = $pos.top - $(coin_window).outerHeight() - 10;
					$left = $pos.left + ($(obj).outerWidth()/2) - ($(coin_window).outerWidth()/2);
					break;
				case 'ar': /* above right */
					$top = $pos.top - $(coin_window).outerHeight() - 10;
					$left = $pos.left + $(obj).outerWidth() - $(coin_window).outerWidth();
					break;
				case 'bl': /* bottom left */
					$top = $pos.top + $(obj).outerHeight() + 10;
					$left = $pos.left;
					break;
				case 'bc': /* bottom center */
					$top = $pos.top + $(obj).outerHeight() + 10;
					$left = $pos.left + ($(obj).outerWidth()/2) - ($(coin_window).outerWidth()/2);
					break;
				case 'br': /* bottom right */
					$top = $pos.top + $(obj).outerHeight() + 10;
					$left = $pos.left + $(obj).outerWidth() - $(coin_window).outerWidth();
					break;
			}
			$(coin_window).stop().animate({'z-index':99999999999,'top':$top,'left':$left},150).show();
		}
	}
	, counter: []
	, counters: function(){
		$addresses = [];
		$.each(CoinWidgetCom.config,function(i,v){
			$instance = i;
			$config = v;
			if ($config.counter != 'hide')
				$addresses.push($instance+'_'+$config.currency+'_'+$config.wallet_address);
			else {
				if ($config.auto_show)
					$("span[data-coinwidget-instance='"+i+"']").find('> a').click();
			}
		});
		if ($addresses.length) {
			CoinWidgetCom.loader.script({
				id: 'COINWIDGETCOM_INFO'
				, source: (CoinWidgetCom.source+'lookup.php?data='+$addresses.join('|'))
				, callback: function(){
					if (typeof COINWIDGETCOM_DATA == 'object') {
						CoinWidgetCom.counter = COINWIDGETCOM_DATA;
						$.each(CoinWidgetCom.counter,function(i,v){
							$config = CoinWidgetCom.config[i];
							if (v == null) v = {count:0,amount:0};
							$("span[data-coinwidget-instance='"+i+"']").find('> span').html($config.counter=='count'?v.count:(v.amount.toFixed($config.decimals)+' '+$config.lbl_amount));
							if ($config.auto_show) {
								$("span[data-coinwidget-instance='"+i+"']").find('> a').click();
							}
						});
					}
				}
			});
		}
	}
	, show: function(obj) {
		$instance = $(obj).parent().attr('data-coinwidget-instance');
		$config = CoinWidgetCom.config[$instance];
		coin_window = "#COINWIDGETCOM_WINDOW_"+$instance;
		$(".COINWIDGETCOM_WINDOW").css({'z-index':99999999998});
		if (!$(coin_window).length) {
			$html = ''
				  + ''+$config.lbl_address+''
				  + '<input type="text" readonly onclick="this.select();" value="'+$config.wallet_address+'" />'
				  + 'CoinWidget.com'
  				  + ''
  				  + 'x'
  				  + ''
				  ;

			if ($config.counter != 'hide') {
				$html += '0'+$config.lbl_count+''
				  	  + '0.00'+$config.lbl_amount+''
				  	  ;
			}

			if ($config.qrcode) {
				$html += ''
				  	   + ''
				  	   ;
			}

			var $div = $('

');
			$('body').append($div);
			$div.attr({
				'id': 'COINWIDGETCOM_WINDOW_'+$instance
			}).addClass('COINWIDGETCOM_WINDOW COINWIDGETCOM_WINDOW_'+$config.currency.toUpperCase()+' COINWIDGETCOM_WINDOW_'+$config.alignment.toUpperCase()).html($html).unbind('click').bind('click',function(){
				$(".COINWIDGETCOM_WINDOW").css({'z-index':99999999998});
				$(this).css({'z-index':99999999999});
			});
			if ($config.qrcode) {
				$(coin_window).find('.COINWIDGETCOM_QRCODE').on('mouseenter click',function(){
					$config = CoinWidgetCom.config[$(this).attr('data-coinwidget-instance')];
					$lrg = $(this).parent().find('.COINWIDGETCOM_QRCODE_LARGE');
					if ($lrg.is(':visible')) {
						$lrg.hide();
						return;
					}
					$lrg.attr({
						src: CoinWidgetCom.source +'qr/?address='+$config.wallet_address
					}).show();
				}).on('mouseleave',function(){
					$lrg = $(this).parent().find('.COINWIDGETCOM_QRCODE_LARGE');
					$lrg.hide();
				});
			}
		} else {
			if ($(coin_window).is(':visible')) {
				CoinWidgetCom.hide($instance);
				return;
			}
		}

		CoinWidgetCom.window_position($instance);
		$(coin_window).show();

		$pos = $(coin_window).find('input').position();

		$(coin_window).find('img.COINWIDGET_INPUT_ICON').css({'top':$pos.top+3,'left':$pos.left+3});
		$(coin_window).find('.COINWIDGETCOM_WALLETURI').css({'top':$pos.top+3,'left':$pos.left+$(coin_window).find('input').outerWidth()+3});

		if ($config.counter != 'hide') {
			$counters = CoinWidgetCom.counter[$instance];

			if ($counters == null) {
				$counters = {
					count: 0,
					amount: 0
				};
			}
		 	if ($counters.count == null) $counters.count = 0;
		 	if ($counters.amount == null) $counters.amount = 0;

			$(coin_window).find('.COINWIDGETCOM_COUNT').html($counters.count+ ''+$config.lbl_count+'');
			$(coin_window).find('.COINWIDGETCOM_AMOUNT').html($counters.amount.toFixed($config.decimals)+ ''+$config.lbl_amount+'');

		}

		if (typeof $config.onShow == 'function')
			$config.onShow();
	}
	, hide: function($instance) {
		$config = CoinWidgetCom.config[$instance];
		coin_window = "#COINWIDGETCOM_WINDOW_"+$instance;
		$(coin_window).fadeOut();
		if (typeof $config.onHide == 'function') {
			$config.onHide();
		}
	}
	, in_array: function(needle,haystack) {
		for (i=0;i<haystack.length;i++) {
			if (haystack[i] == needle) {
				return true;
			}
		}
		return false;
	}
	, loader: {
		loading_jquery: false,
		script: function(obj){
			if (!document.getElementById(obj.id)) {
				var x = document.createElement('script');
				x.onreadystatechange = function(){
					switch (this.readyState) {
						case 'complete':
						case 'loaded':
							obj.callback();
							break;
					}
				};
				x.onload = function(){
					obj.callback();
				};
				x.src = obj.source;
				x.id  = obj.id;
				document.lastChild.firstChild.appendChild(x);
			}
		}
		, stylesheet: function(){
			if (!$("#COINWDIGETCOM_STYLESHEET").length) {
				var $link = $('<link/>');
				$("head").append($link);
				$link.attr({
					id 		: 'COINWIDGETCOM_STYLESHEET'
					, rel 	: 'stylesheet'
					, type 	: 'text/css'
					, href 	: CoinWidgetCom.source+'coin.css'
				});
			}
		}
		, jquery: function(){
			if (!window.jQuery && !CoinWidgetCom.loader.loading_jquery) {
				$prefix = window.location.origin.indexOf('file://')!=-1?'http:':'';
				CoinWidgetCom.loader.script({
					id			: 'COINWIDGETCOM_JQUERY'
					, source 	: $prefix + '//ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js'
					, callback  : function(){
						CoinWidgetCom.init();
					}
				});
				return;
			}
			CoinWidgetCom.init();
		}
	}
};<commit_msg>cleanup<commit_after>/**

Donations welcome:
	BTC: 122MeuyZpYz4GSHNrF98e6dnQCXZfHJeGS
	LTC: LY1L6M6yG26b4sRkLv4BbkmHhPn8GR5fFm
		~ Thank you!

------------

MIT License (MIT)

Copyright (c) 2013 http://coinwidget.com/
Copyright (c) 2013 http://scotty.cc/

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

*/

if (typeof CoinWidgetComCounter != 'number')
var CoinWidgetComCounter = 0;

if (typeof CoinWidgetCom != 'object')
var CoinWidgetCom = {
	source: 'http://coinwidget.com/widget/'
	, config: []
	, go :function(config) {
		config = CoinWidgetCom.validate(config);
		CoinWidgetCom.config[CoinWidgetComCounter] = config;
		CoinWidgetCom.loader.jquery();
		document.write('');
		CoinWidgetComCounter++;
	}
	, validate: function(config) {
		var $accepted = [];
		$accepted['currencies'] = ['bitcoin','litecoin'];
		$accepted['counters'] = ['count','amount','hide'];
		$accepted['alignment'] = ['al','ac','ar','bl','bc','br'];
		if (!config.currency || !CoinWidgetCom.in_array(config.currency,$accepted['currencies']))
			config.currency = 'bitcoin';
		if (!config.counter || !CoinWidgetCom.in_array(config.counter,$accepted['counters']))
			config.counter = 'count';
		if (!config.alignment || !CoinWidgetCom.in_array(config.alignment,$accepted['alignment']))
			config.alignment = 'bl';
		if (typeof config.qrcode != 'boolean')
			config.qrcode = true;
		if (typeof config.auto_show != 'boolean')
			config.auto_show = false;
		if (!config.wallet_address)
			config.wallet_address = 'My '+ config.currency +' wallet_address is missing!';
		if (!config.lbl_button)
			config.lbl_button = 'Donate';
		if (!config.lbl_address)
			config.lbl_address = 'My Bitcoin Address:';
		if (!config.lbl_count)
			config.lbl_count = 'Donation';
		if (!config.lbl_amount)
			config.lbl_amount = 'BTC';
		if (typeof config.decimals != 'number' || config.decimals < 0 || config.decimals > 10)
			config.decimals = 4;

		return config;
	}
	, init: function(){
		CoinWidgetCom.loader.stylesheet();
		$(window).resize(function(){
			CoinWidgetCom.window_resize();
		});
		setTimeout(function(){
			/* this delayed start gives the page enough time to
			   render multiple widgets before pinging for counts.
			*/
			CoinWidgetCom.build();
		},300);
	}
	, build: function(){
		$containers = $("span[data-coinwidget-instance]");
		$containers.each(function(i,v){
			$config = CoinWidgetCom.config[$(this).attr('data-coinwidget-instance')];
			$counter = $config.counter == 'hide'?'':('');
			$button = ''+$config.lbl_button+''+$counter;
			$(this).html($button);
			$(this).find('> a').unbind('click').click(function(e){
				e.preventDefault();
				CoinWidgetCom.show(this);
			});
		});
		CoinWidgetCom.counters();
	}
	, window_resize: function(){
		$.each(CoinWidgetCom.config,function(i,v){
			CoinWidgetCom.window_position(i);
		});
	}
	, window_position: function($instance){
		$config = CoinWidgetCom.config[$instance];
		coin_window = "#COINWIDGETCOM_WINDOW_"+$instance;
		if ($(coin_window).is(':visible')) {
			obj = "span[data-coinwidget-instance='"+$instance+"'] > a";
			/* 	to make alignment relative to the full width of the container instead
			of just the button change this occurence of $(obj) to $(obj).parent(),
			do the same for the occurences within the switch statement. */
			$pos = $(obj).offset();
			switch ($config.alignment) {
				default:
				case 'al': /* above left */
					$top = $pos.top - $(coin_window).outerHeight() - 10;
					$left = $pos.left;
					break;
				case 'ac': /* above center */
					$top = $pos.top - $(coin_window).outerHeight() - 10;
					$left = $pos.left + ($(obj).outerWidth()/2) - ($(coin_window).outerWidth()/2);
					break;
				case 'ar': /* above right */
					$top = $pos.top - $(coin_window).outerHeight() - 10;
					$left = $pos.left + $(obj).outerWidth() - $(coin_window).outerWidth();
					break;
				case 'bl': /* bottom left */
					$top = $pos.top + $(obj).outerHeight() + 10;
					$left = $pos.left;
					break;
				case 'bc': /* bottom center */
					$top = $pos.top + $(obj).outerHeight() + 10;
					$left = $pos.left + ($(obj).outerWidth()/2) - ($(coin_window).outerWidth()/2);
					break;
				case 'br': /* bottom right */
					$top = $pos.top + $(obj).outerHeight() + 10;
					$left = $pos.left + $(obj).outerWidth() - $(coin_window).outerWidth();
					break;
			}
			$(coin_window).stop().animate({'z-index':99999999999,'top':$top,'left':$left},150).show();
		}
	}
	, counter: []
	, counters: function(){
		$addresses = [];
		$.each(CoinWidgetCom.config,function(i,v){
			$instance = i;
			$config = v;
			if ($config.counter != 'hide')
				$addresses.push($instance+'_'+$config.currency+'_'+$config.wallet_address);
			else {
				if ($config.auto_show)
					$("span[data-coinwidget-instance='"+i+"']").find('> a').click();
			}
		});
		if ($addresses.length) {
			CoinWidgetCom.loader.script({
				id: 'COINWIDGETCOM_INFO'
				, source: (CoinWidgetCom.source+'lookup.php?data='+$addresses.join('|'))
				, callback: function(){
					if (typeof COINWIDGETCOM_DATA == 'object') {
						CoinWidgetCom.counter = COINWIDGETCOM_DATA;
						$.each(CoinWidgetCom.counter,function(i,v){
							$config = CoinWidgetCom.config[i];
							if (v == null) v = {count:0,amount:0};
							$("span[data-coinwidget-instance='"+i+"']").find('> span').html($config.counter=='count'?v.count:(v.amount.toFixed($config.decimals)+' '+$config.lbl_amount));
							if ($config.auto_show) {
								$("span[data-coinwidget-instance='"+i+"']").find('> a').click();
							}
						});
					}
				}
			});
		}
	}
	, show: function(obj) {
		$instance = $(obj).parent().attr('data-coinwidget-instance');
		$config = CoinWidgetCom.config[$instance];
		coin_window = "#COINWIDGETCOM_WINDOW_"+$instance;
		$(".COINWIDGETCOM_WINDOW").css({'z-index':99999999998});
		if (!$(coin_window).length) {
			$html = ''
				  + ''+$config.lbl_address+''
				  + '<input type="text" readonly onclick="this.select();" value="'+$config.wallet_address+'" />'
				  + 'CoinWidget.com'
  				  + ''
  				  + 'x'
  				  + ''
				  ;
			if ($config.counter != 'hide') {
				$html += '0'+$config.lbl_count+''
				  	  + '0.00'+$config.lbl_amount+''
				  	  ;
			}
			if ($config.qrcode) {
				$html += ''
				  	   + ''
				  	   ;
			}
			var $div = $('

');
			$('body').append($div);
			$div.attr({
				'id': 'COINWIDGETCOM_WINDOW_'+$instance
			}).addClass('COINWIDGETCOM_WINDOW COINWIDGETCOM_WINDOW_'+$config.currency.toUpperCase()+' COINWIDGETCOM_WINDOW_'+$config.alignment.toUpperCase()).html($html).unbind('click').bind('click',function(){
				$(".COINWIDGETCOM_WINDOW").css({'z-index':99999999998});
				$(this).css({'z-index':99999999999});
			});
			if ($config.qrcode) {
				$(coin_window).find('.COINWIDGETCOM_QRCODE').on('mouseenter click',function(){
					$config = CoinWidgetCom.config[$(this).attr('data-coinwidget-instance')];
					$lrg = $(this).parent().find('.COINWIDGETCOM_QRCODE_LARGE');
					if ($lrg.is(':visible')) {
						$lrg.hide();
						return;
					}
					$lrg.attr({
						src: CoinWidgetCom.source +'qr/?address='+$config.wallet_address
					}).show();
				}).on('mouseleave',function(){
					$lrg = $(this).parent().find('.COINWIDGETCOM_QRCODE_LARGE');
					$lrg.hide();
				});
			}
		} else {
			if ($(coin_window).is(':visible')) {
				CoinWidgetCom.hide($instance);
				return;
			}
		}
		CoinWidgetCom.window_position($instance);
		$(coin_window).show();
		$pos = $(coin_window).find('input').position();
		$(coin_window).find('img.COINWIDGET_INPUT_ICON').css({'top':$pos.top+3,'left':$pos.left+3});
		$(coin_window).find('.COINWIDGETCOM_WALLETURI').css({'top':$pos.top+3,'left':$pos.left+$(coin_window).find('input').outerWidth()+3});
		if ($config.counter != 'hide') {
			$counters = CoinWidgetCom.counter[$instance];
			if ($counters == null) {
				$counters = {
					count: 0,
					amount: 0
				};
			}
		 	if ($counters.count == null) $counters.count = 0;
		 	if ($counters.amount == null) $counters.amount = 0;
			$(coin_window).find('.COINWIDGETCOM_COUNT').html($counters.count+ ''+$config.lbl_count+'');
			$(coin_window).find('.COINWIDGETCOM_AMOUNT').html($counters.amount.toFixed($config.decimals)+ ''+$config.lbl_amount+'');
		}
		if (typeof $config.onShow == 'function')
			$config.onShow();
	}
	, hide: function($instance) {
		$config = CoinWidgetCom.config[$instance];
		coin_window = "#COINWIDGETCOM_WINDOW_"+$instance;
		$(coin_window).fadeOut();
		if (typeof $config.onHide == 'function') {
			$config.onHide();
		}
	}
	, in_array: function(needle,haystack) {
		for (i=0;i<haystack.length;i++) {
			if (haystack[i] == needle) {
				return true;
			}
		}
		return false;
	}
	, loader: {
		loading_jquery: false,
		script: function(obj){
			if (!document.getElementById(obj.id)) {
				var x = document.createElement('script');
				x.onreadystatechange = function(){
					switch (this.readyState) {
						case 'complete':
						case 'loaded':
							obj.callback();
							break;
					}
				};
				x.onload = function(){
					obj.callback();
				};
				x.src = obj.source;
				x.id  = obj.id;
				document.lastChild.firstChild.appendChild(x);
			}
		}
		, stylesheet: function(){
			if (!$("#COINWDIGETCOM_STYLESHEET").length) {
				var $link = $('<link/>');
				$("head").append($link);
				$link.attr({
					id 		: 'COINWIDGETCOM_STYLESHEET'
					, rel 	: 'stylesheet'
					, type 	: 'text/css'
					, href 	: CoinWidgetCom.source+'coin.css'
				});
			}
		}
		, jquery: function(){
			if (!window.jQuery && !CoinWidgetCom.loader.loading_jquery) {
				$prefix = window.location.origin.indexOf('file://')!=-1?'http:':'';
				CoinWidgetCom.loader.script({
					id			: 'COINWIDGETCOM_JQUERY'
					, source 	: $prefix + '//ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js'
					, callback  : function(){
						CoinWidgetCom.init();
					}
				});
				return;
			}
			CoinWidgetCom.init();
		}
	}
};<|endoftext|>


<commit_before>function processTextArea(domId) {
    var items = [];
    var lines = $('#' + domId).val().split('\n');
    console.log(lines);
    for (var i = 0; i < lines.length; i++) {
        //code here using lines[i] which will give you each line
        var item = lines[i].split('#');
        if (item.indexOf('') == -1) {
            items.push({
                'url': item[0],
                'AP_CODE': item[1],
                'city': item[2]
            });
        }
    }
    return items;
}
function getData(json) {

    var url = '/putImage';
    function callback(data, textStatus, jqXHR) {
        console.log(data);
    }

    console.log('going to send this...');
    console.log(json);
    $.post(url, { 'images': json }, callback);
}
function buttonClick() {
    //getData(processTextArea('sourceText'));
    var json = processTextArea('sourceText');
    //console.log(json);
    for (var i in json) {
        getData([json[i]]);
    }
}
function whatCity() {

    var inputId = 'sourceText2';
    var url = '/labels';
    function callback(data, textStatus, jqXHR) {
        console.log(data);
    }

    console.log('going to send this whatCity...', { 'img': $('#' + inputId)[0].value });
    $.post(url, { 'img': $('#' + inputId)[0].value }, callback);
}
function updateTable(inputId, domId) {

    var text = '

No.	Airport	city	url

';

    var lines = $('#' + inputId).val().split('\n');
    for (var i in lines) {
        var item = lines[i].split('#');
        text += '
' + i + '	' + item[1] + '	' + item[2] + '	' + item[0] + '
';
    }
    text += '

';
    $('#' + domId)[0].innerHTML = text;
}
function callIG() {
    var sample = {
        "data": [{
            "comments": {
                "count": 0
            },
            "caption": {
                "created_time": "1296710352",
                "text": "Inside le truc #foodtruck",
                "from": {
                    "username": "kevin",
                    "full_name": "Kevin Systrom",
                    "type": "user",
                    "id": "3"
                },
                "id": "26621408"
            },
            "likes": {
                "count": 15
            },
            "link": "http://instagr.am/p/BWrVZ/",
            "user": {
                "username": "kevin",
                "full_name": "Kevin Systrom",
                "profile_picture": "http://distillery.s3.amazonaws.com/profiles/profile_3_75sq_1295574122.jpg",
                "id": "3"
            },
            "created_time": "1296710327",
            "images": {
                "low_resolution": {
                    "url": "http://distillery.s3.amazonaws.com/media/2011/02/02/6ea7baea55774c5e81e7e3e1f6e791a7_6.jpg",
                    "width": 306,
                    "height": 306
                },
                "thumbnail": {
                    "url": "http://distillery.s3.amazonaws.com/media/2011/02/02/6ea7baea55774c5e81e7e3e1f6e791a7_5.jpg",
                    "width": 150,
                    "height": 150
                },
                "standard_resolution": {
                    "url": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQJeASsQnKnr95B6DLSYN3IfwpnN3hmbVoGJzmZY_9wjHyf_zmK",
                    "width": 612,
                    "height": 612
                }
            },
            "type": "image",
            "users_in_photo": [],
            "filter": "Earlybird",
            "tags": ["foodtruck"],
            "id": "22721881",
            "location": {
                "latitude": 37.778720183610183,
                "longitude": -122.3962783813477,
                "id": "520640",
                "street_address": "",
                "name": "Le Truc"
            }
        }]
    };

    var url = '/putIG';
    function callback(data, textStatus, jqXHR) {
        console.log(data);
    }

    console.log('going to send this putIG...');
    $.post(url, sample, callback);
}<commit_msg>a lot<commit_after>function processTextArea(domId) {
    var items = [];
    var lines = $('#' + domId).val().split('\n');
    console.log(lines);
    for (var i = 0; i < lines.length; i++) {
        //code here using lines[i] which will give you each line
        var item = lines[i].split('#');
        if (item.indexOf('') == -1) {
            items.push({
                'url': item[0],
                'AP_CODE': item[1],
                'city': item[2]
            });
        }
    }
    return items;
}
function getData(json) {

    var url = '/putImage';
    function callback(data, textStatus, jqXHR) {
        console.log(data);
    }

    console.log('going to send this...');
    console.log(json);
    $.post(url, { 'images': json }, callback);
}
function buttonClick() {
    //getData(processTextArea('sourceText'));
    var json = processTextArea('sourceText');
    //console.log(json);
    for (var i in json) {
        getData([json[i]]);
    }
}
function whatCity() {

    var inputId = 'sourceText2';
    var url = '/labels';
    function callback(data, textStatus, jqXHR) {
        console.log(data);
    }

    console.log('going to send this whatCity...', { 'img': $('#' + inputId)[0].value });
    $.post(url, { 'img': $('#' + inputId)[0].value }, callback);
}
function updateTable(inputId, domId) {

    var text = '

No.	Airport	city	url

';

    var lines = $('#' + inputId).val().split('\n');
    for (var i in lines) {
        var item = lines[i].split('#');
        text += '
' + i + '	' + item[1] + '	' + item[2] + '	' + item[0] + '
';
    }
    text += '

';
    $('#' + domId)[0].innerHTML = text;
}
function callIG() {
    var sample = {
        "data": [{
            "comments": {
                "count": 0
            },
            "caption": {
                "created_time": "1296710352",
                "text": "Inside le truc #foodtruck",
                "from": {
                    "username": "kevin",
                    "full_name": "Kevin Systrom",
                    "type": "user",
                    "id": "3"
                },
                "id": "26621408"
            },
            "likes": {
                "count": 15
            },
            "link": "http://instagr.am/p/BWrVZ/",
            "user": {
                "username": "kevin",
                "full_name": "Kevin Systrom",
                "profile_picture": "http://distillery.s3.amazonaws.com/profiles/profile_3_75sq_1295574122.jpg",
                "id": "3"
            },
            "created_time": "1296710327",
            "images": {
                "low_resolution": {
                    "url": "http://distillery.s3.amazonaws.com/media/2011/02/02/6ea7baea55774c5e81e7e3e1f6e791a7_6.jpg",
                    "width": 306,
                    "height": 306
                },
                "thumbnail": {
                    "url": "http://distillery.s3.amazonaws.com/media/2011/02/02/6ea7baea55774c5e81e7e3e1f6e791a7_5.jpg",
                    "width": 150,
                    "height": 150
                },
                "standard_resolution": {
                    "url": "https://instagram.fkul10-1.fna.fbcdn.net/t51.2885-15/e35/16230601_1780814025572841_3618244784189079552_n.jpg",
                    "width": 612,
                    "height": 612
                }
            },
            "type": "image",
            "users_in_photo": [],
            "filter": "Earlybird",
            "tags": ["foodtruck"],
            "id": "22721881",
            "location": {
                "latitude": 37.778720183610183,
                "longitude": -122.3962783813477,
                "id": "520640",
                "street_address": "",
                "name": "Le Truc"
            }
        }]
    };

    var url = '/putIG';
    function callback(data, textStatus, jqXHR) {
        console.log(data);
    }

    console.log('going to send this putIG...');
    $.post(url, sample, callback);
}<|endoftext|>


<commit_before>import { eventChannel } from 'redux-saga';
import { all, fork, select, take, takeEvery, takeLatest, call, put } from 'redux-saga/effects';
import axios from 'axios';
import { EDIT_LIST_ITEM_ADDED, SERVER_UPDATED } from '../constants/actions';
import debounce from '../misc/debounce';
import { API_PREFIX } from '../misc/const';
import { aKeyPressed, aServerUpdateReceived, aServerAddReceived } from '../actions/app.actions';
import { selectApiKey } from '.';
import { openTimedMessage } from './error.saga';

function keyPressEventChannel() {
    return eventChannel(emitter => {
        const keyPressHandler = debounce(evt => {
            emitter(aKeyPressed({
                key: evt.key,
                shift: evt.shiftKey,
                ctrl: evt.ctrlKey
            }));
        }, 1, true);

        const onKeyPress = evt => {
            if (evt.key === 'Tab') {
                evt.preventDefault();
            }

            keyPressHandler(evt);
        };

        window.addEventListener('keydown', onKeyPress);

        return () => {
            window.removeEventListener('keydown', onKeyPress);
        };
    });
}

export function *watchKeyPress() {
    const channel = keyPressEventChannel();

    while (true) {
        const action = yield take(channel);

        yield put(action);
    }
}

export const selectRequestList = state => state.getIn(['edit', 'requestList'])
    .map(item => item.get('req'));

export function *updateServerData() {
    const apiKey = yield select(selectApiKey);
    const requestList = yield select(selectRequestList);

    try {
        const response = yield call(
            axios.patch,
            `${API_PREFIX}/data/multiple`,
            { list: requestList },
            { headers: { 'Authorization': apiKey } }
        );

        yield put(aServerUpdateReceived(response));
    }
    catch (err) {
        yield call(openTimedMessage, 'Error updating data on server!');

        yield put(aServerUpdateReceived(null));
    }
}

export function *addServerDataRequest({ item, fields, page }) {
    const apiKey = yield select(selectApiKey);

    try {
        const response = yield call(
            axios.post,
            `${API_PREFIX}/data/${page}`,
            item,
            { headers: { 'Authorization': apiKey } }
        );

        yield put(aServerAddReceived({ response, fields, page }));
    }
    catch (err) {
        yield call(openTimedMessage, 'Error adding data to server!');
    }
}

export const selectAddData = state => ({
    fields: state.getIn(['edit', 'addFields']),
    item: state.getIn(['edit', 'addFieldsString'])
});

export function *addServerData({ page }) {
    // data is validated by reducer
    const { fields, item } = yield select(selectAddData);

    if (fields && item) {
        yield call(addServerDataRequest, { page, item, fields });
    }
}

export default function *appSaga() {
    yield all([
        fork(watchKeyPress),
        takeEvery(EDIT_LIST_ITEM_ADDED, addServerData),
        takeLatest(SERVER_UPDATED, updateServerData)
    ]);
}

<commit_msg>Use meta key for navigation on macOS<commit_after>import { eventChannel } from 'redux-saga';
import { all, fork, select, take, takeEvery, takeLatest, call, put } from 'redux-saga/effects';
import axios from 'axios';
import { EDIT_LIST_ITEM_ADDED, SERVER_UPDATED } from '../constants/actions';
import debounce from '../misc/debounce';
import { API_PREFIX } from '../misc/const';
import { aKeyPressed, aServerUpdateReceived, aServerAddReceived } from '../actions/app.actions';
import { selectApiKey } from '.';
import { openTimedMessage } from './error.saga';

function keyPressEventChannel() {
    return eventChannel(emitter => {
        const keyPressHandler = debounce(evt => {
            emitter(aKeyPressed({
                key: evt.key,
                shift: evt.shiftKey,
                ctrl: evt.ctrlKey || evt.metaKey
            }));
        }, 1, true);

        const onKeyPress = evt => {
            const tab = evt.key === 'Tab';
            const nav = (evt.ctrlKey || evt.metaKey) && evt.key.indexOf('Arrow') === 0;

            if (tab || nav) {
                evt.preventDefault();
            }

            keyPressHandler(evt);
        };

        window.addEventListener('keydown', onKeyPress);

        return () => {
            window.removeEventListener('keydown', onKeyPress);
        };
    });
}

export function *watchKeyPress() {
    const channel = keyPressEventChannel();

    while (true) {
        const action = yield take(channel);

        yield put(action);
    }
}

export const selectRequestList = state => state.getIn(['edit', 'requestList'])
    .map(item => item.get('req'));

export function *updateServerData() {
    const apiKey = yield select(selectApiKey);
    const requestList = yield select(selectRequestList);

    try {
        const response = yield call(
            axios.patch,
            `${API_PREFIX}/data/multiple`,
            { list: requestList },
            { headers: { 'Authorization': apiKey } }
        );

        yield put(aServerUpdateReceived(response));
    }
    catch (err) {
        yield call(openTimedMessage, 'Error updating data on server!');

        yield put(aServerUpdateReceived(null));
    }
}

export function *addServerDataRequest({ item, fields, page }) {
    const apiKey = yield select(selectApiKey);

    try {
        const response = yield call(
            axios.post,
            `${API_PREFIX}/data/${page}`,
            item,
            { headers: { 'Authorization': apiKey } }
        );

        yield put(aServerAddReceived({ response, fields, page }));
    }
    catch (err) {
        yield call(openTimedMessage, 'Error adding data to server!');
    }
}

export const selectAddData = state => ({
    fields: state.getIn(['edit', 'addFields']),
    item: state.getIn(['edit', 'addFieldsString'])
});

export function *addServerData({ page }) {
    // data is validated by reducer
    const { fields, item } = yield select(selectAddData);

    if (fields && item) {
        yield call(addServerDataRequest, { page, item, fields });
    }
}

export default function *appSaga() {
    yield all([
        fork(watchKeyPress),
        takeEvery(EDIT_LIST_ITEM_ADDED, addServerData),
        takeLatest(SERVER_UPDATED, updateServerData)
    ]);
}

<|endoftext|>


<commit_before>var React = require('react-native');
var styles = require("../styles.js");
var MOCK_DATA = require("../mockData.js");

var {View, ListView, Text,} = React;

class Marks extends React.Component {

  constructor(props) {
    super(props);
    this.state = {
      dataSource: new ListView.DataSource({
        rowHasChanged: (row1, row2) => row1 !== row2,
      }),
      loaded: false
    };
   }

  componentDidMount() {
    this.fetchData();
  }

  fetchData(){
    this.setState({
      dataSource: this.state.dataSource.cloneWithRows(MOCK_DATA),
      loaded: true,
    });
  }

  renderLoadingView() {
   return (
     <View style={styles.container}>
       <Text>
         Loading messages...
       </Text>
     </View>
   );
  }

  render() {
    if (!this.state.loaded) {
      return this.renderLoadingView();
    }
    return (
      <ListView
        dataSource={this.state.dataSource}
        renderRow={this.renderMessage}
        style={styles.listView} />
    );
  }

  renderMessage(message) {
    console.log(message)
    return (
    <View style={styles.container}>
      <Text> </Text>
      <Text style={{textAlign: 'right', fontSize: 8}}> {message.timestamp} </Text>
      <Text> {message.body} </Text>
    </View>
    );
  }
};

module.exports = Marks;
<commit_msg>fetch code for eventualy GET request<commit_after>var React = require('react-native');
var styles = require("../styles.js");
var MOCK_DATA = require("../mockData.js");

var {View, ListView, Text,} = React;

class Marks extends React.Component {

  constructor(props) {
    super(props);
    this.state = {
      dataSource: new ListView.DataSource({
        rowHasChanged: (row1, row2) => row1 !== row2,
      }),
      loaded: false
    };
   }

  componentDidMount() {
    this.fetchData();
  }

  fetchData(){
    this.setState({
      dataSource: this.state.dataSource.cloneWithRows(MOCK_DATA),
      loaded: true,
    });

    /*

    fetch(REQUEST_URL)
      .then((response) => response.json())
      .then((responseData) => {
        this.setState({
          dataSource: this.state.dataSource.cloneWithRows(responseData.movies),
          loaded: true,
        });
      })
      .done();

    */
  }

  renderLoadingView() {
   return (
     <View style={styles.container}>
       <Text>
         Loading messages...
       </Text>
     </View>
   );
  }

  render() {
    if (!this.state.loaded) {
      return this.renderLoadingView();
    }
    return (
      <ListView
        dataSource={this.state.dataSource}
        renderRow={this.renderMessage}
        style={styles.listView} />
    );
  }

  renderMessage(message) {
    console.log(message)
    return (
    <View style={styles.container}>
      <Text> </Text>
      <Text style={{textAlign: 'right', fontSize: 8}}> {message.timestamp} </Text>
      <Text> {message.body} </Text>
    </View>
    );
  }
};

module.exports = Marks;
<|endoftext|>


<commit_before>function makeDynamic() {
    // make our testSteps sortable
    $(".testSteps").sortable({
        stop : function(event, ui) {
            buildTable($(ui.item).parent().parent());
        }
    });
    // make the scenarios sortable
    $("#tests").sortable({
        handle : ".what"
    });
    // make the tables (example data) sortable
    $("tbody").sortable();
    // setup our new dropdowns using the chosen plugin
    $('select').each(function() {
        var placeholder = $(this).attr('placeholder');
        if ($(this).parent().is("td")) {
            placeholder = " ";
        }
        if ($(this).attr('multiple') == 'multiple') {
            $(this).chosen({
                placeholder_text_multiple : placeholder,
                width : 'auto',
                disable_search_threshold : 4,
                inherit_select_classes : true,
            });
        } else {
            $(this).chosen({
                placeholder_text_single : placeholder,
                width : $(this).width() + 30,
                disable_search_threshold : 4,
                inherit_select_classes : true,
            });
        }
    });
    // allow editing of an any span
    $('span.any').dblclick(function() {
        var input = $("<input type='text' class='small' />").keyup(resizeInput).each(resizeInput).blur(function() {
            if ($(this).val() == "") {
                $(this).parent().html("...");
            }
        });
        $(this).html(input);
    });
    // allow the toggling an opt span
    $('span.opt').dblclick(function() {
        if ($(this).css('opacity') > 0.5)
            $(this).css({
                opacity : 0.2
            });
        else
            $(this).css({
                opacity : 1
            });
    });
    // keep the size of our input fields under control
    $('input.small').each(function() {
        $(this).keyup(resizeInput).each(resizeInput);
    });
    // keep the size of our textareas under control
    $('textarea').keyup(function() {
        $(this).attr('rows', ($(this).val().split("\n").length || 1));
    });

    // mark required fields in red
    $('.required').keyup(function() {
        checkRequired($(this));
    });

    // initialize the delete dialog
    $("#delete").dialog({
        autoOpen : false,
        modal : true
    });
}

function checkRequired(element) {
    if (element.val() == "") {
        element.addClass("red");
    } else {
        element.removeClass("red");
    }
    // check to see if all required things are filled in
    if ($('.red:visible').length) {
        $('#exportFile').button("disable");
        $('#exportJIRA').button("disable");
    } else {
        $('#exportFile').button("enable");
        $('#exportJIRA').button("enable");
    }
}

function fillTag(el) {
    if (typeof tags !== 'undefined' && tags.length > 0) {
        $(el).attr('placeholder','Choose a Tag...')
        $(el).autocomplete({
            minLength : 0,
            source : tags,
            select : function(event, ui) {
                addTag(el, ui.item.value);
                return false;
            },
        }).click(function() {
            $(this).autocomplete("search", "");
        }).keyup(function(e) {
            if(e.keyCode == 32 || e.keyCode == 13){
                addTag(el);
            }
        }).blur(function(){
            addTag(el);
        });
    }
}
function addTag(el, tag) {
    if (tag == "" || tag === undefined ) {
        tag = $(el).val();
        if (tag == "") {
            return;
        }
    }
    // build the environment
    var span = $("");
    span.html(tag);
    span.addClass('tag');
    span.click(function(){
        $(this).remove();
    });
    $(el).after(span);
    $(el).val("");
}

function addScenario() {
    var scenario = $("
");
    var tags = $("<input class='purple small' placeholder='Scenario Tags'>");
    fillTag(tags);
    var holder = $("
");
    var what = $("");
    what.html("Scenario:");
    var title = $("<input class='green small required red' placeholder='Test Case Name' type='text' required>");
    var description = $("<textarea rows='1' placeholder='Test Case Description'>");
    var steps = $("
");
    var addSteps = $("<button onclick='addTestStep(this)' class='ui-button ui-button-small'>");
    addSteps.html("Add Test Step");
    var addTable = $("<button onclick='addDataTable(this)' class='addTable ui-button ui-button-small' style='display:none;'>");
    addTable.html("Add Data Table");
    var deleteButton = $("

");
    var linkButton = $("

");
    holder.append(what).append(" ").append(title).append($("
")).append(description);
    scenario.append(tags).append(holder).append(steps).append(addSteps).append(addTable).append(deleteButton);
    if (jiraOptions.project !== "") {
        scenario.append(linkButton);
    }
    $('#tests').append(scenario);
    makeDynamic();
}
function addTestStep(el) {
    var testStep = $("
");
    var editHolder = $("
");
    editHolder.append($(""));
    var deleteHolder = $("
");
    deleteHolder.append($(""));
    var select = $("<select class='blue' onchange='void(0);'>");
    select.append($("<option>"));
    select.append($("<option>Given</option>"));
    select.append($("<option>When</option>"));
    select.append($("<option>Then</option>"));
    testStep.append(editHolder).append(deleteHolder).append(select);
    $(el).parent().find('.testSteps').append(testStep);
    makeDynamic();
    fillStep(select, "");
}
function fillStep(el, initialVal) {
    $(el).next().nextAll().remove();
    var input = $("<input type='text' class='small' value='" + initialVal + "'/>");
    var autocompletes = [];
    for (var i = 0; i < testSteps.length; i++) {
        autocompletes.push({
            label : testSteps[i].string.stripTags(),
            value : testSteps[i].string,
            order : i
        });
    }
    input.autocomplete({
        minLength : 0,
        source : autocompletes,
        focus : function(event, ui) {
            input.val(ui.item.value.stripTags());
            return false;
        },
        select : function(event, ui) {
            fillVars(ui.item.order, $(this));
        },
    }).click(function() {
        $(this).autocomplete("search", "");
    }).blur(function() {
        createStep($(this));
    });
    $(el).next().after(input);
}

function createStep(el) {
    var newStep = $(el).val();
    var type = $(el).prev().prev();
    // Need to determine if this step matches something
    // Check each GWT, replace XXXX with (.*), and do a regex check
    // if any are a match, select it
    for (var i = 0; i < testSteps[step].length; i++) {
        var string = testSteps[step][i].string;
        var regex = string.replace(/(.*?)<\/span>/g, "($1)?");
        regex = regex.replace(/(.*?)<\/span>/g, "(.*?)");
        regex = regex.replace(/XXXX/g, "(.*)");
        regex = regex.stripTags();
        regex = "^" + regex + "$";
        var res = newStep.match(regex);
        if (res != null) {
            fillVars(i, el);
            var inputs = type.parent().children('input,select');
            for (var j = 1; j < res.length; j++) {
                if (res[j] == "XXXX") {
                    res[j] = "";
                }
                $(inputs).eq(j).val(res[j]);
                if ($(inputs).eq(j).is('select')) {
                    $(inputs).eq(j).trigger('chosen:updated');
                }
                buildTable(type.parent().parent().parent());
                makeDynamic();
            }
            return true;
        }
    }
    type.next().nextAll().remove();
    var newStepPieces = newStep.split(/<|>/);
    newStep = "";
    for (i = 0; i < newStepPieces.length; i++) {
        newStep += "" + newStepPieces[i] + "";
        if (newStepPieces[i + 1]) {
            newStep += "<input id='" + rand(10) + "' type='text' class='small' onchange='buildTable(this)' placeholder='<" + newStepPieces[i + 1] + ">' class='new' />";
            i++;
        }
    }
    type.parent().append(newStep);
    buildTable(type.parent().parent().parent());
    makeDynamic();
}

function fillVars(order, el) {
    var testStepString = testSteps[order].string;
    var testStepInputs = testSteps[order].inputs;
    var testStepPieces = testStepString.split("XXXX");
    var type = $(el).prev();
    type.nextAll().remove();
    for (var i = 0; i < testStepPieces.length; i++) {
        type.parent().append("" + testStepPieces[i] + "");
        if (testStepInputs[i] !== undefined) {
            var objID = rand(10);
            if (Object.prototype.toString.call(testStepInputs[i].value) === '[object Array]') {
                var sel = $("<select id='" + objID + "' type='" + testStepInputs[i].key + "' onchange='buildTable(this)' placeholder='<" + testStepInputs[i].key + ">'></select>");
                if (testStepInputs[i].key.endsWith("List")) {
                    sel.attr("multiple", "multiple");
                    sel.append("<option></option>");
                } else {
                    sel.append("<option><" + testStepInputs[i].key + "></option>");
                }
                for (var j = 0; j < testStepInputs[i].value.length; j++) {
                    sel.append("<option>" + testStepInputs[i].value[j] + "</option>");
                }
                type.parent().append(sel);
            } else {
                type.parent().append("<input id='" + objID + "' type='" + testStepInputs[i].value + "' class='small' onchange='buildTable(this)' placeholder='<" + testStepInputs[i].key + ">' />");
            }
        }
    }
    buildTable(type.parent().parent().parent());
    makeDynamic();
}
function addDataTable(el) {
    addTable($(el).parent());
    buildTable($(el).parent());
}
function buildTable(testEl) { // el should be the test element
    if (!$(testEl).hasClass('scenario')) {
        testEl = $(testEl).parent().parent().parent();
    }
    if (!$(testEl).hasClass('scenario')) {
        return false;
    }
    // add a table if needed
    if ($(testEl).find('.examples').length == 0) {
        addTable($(testEl));
        $(testEl).children('.addTable').show();
    }
    // get each variable from our test steps
    var variables = {};
    var scenario = $(testEl).children('.testSteps');
    scenario.children('.testStep').each(function() {
        $(this).children('input, select').each(function() {
            if ($(this).val() == null) {
                var placeholder = $(this).attr('placeholder')
                if (placeholder.startsWith("<") && placeholder.endsWith(">")) {
                    variables[placeholder.substring(1, placeholder.length - 1)] = $(this).attr('id');
                }
                return true;
            }
            if (Object.prototype.toString.call($(this).val()) === '[object Array]') {
                return true;
            }
            if ($(this).hasClass('ui-autocomplete-input')) {
                return true;
            }
            if ($(this).val() == "" && $(this).is("input")) {
                var placeholder = $(this).attr('placeholder')
                variables[placeholder.substring(1, placeholder.length - 1)] = $(this).attr('id');
                return true;
            }
            if ($(this).val().startsWith("<") && $(this).val().endsWith(">")) {
                var placeholder = $(this).val();
                variables[placeholder.substring(1, placeholder.length - 1)] = $(this).attr('id');
                return true;
            }
        });
    });
    var examples = scenario.parent().children('.examples');
    $(examples).each(function() {
        var example = $(this);
        // remove any columns that no longer exist in the variables
        var header = example.children('table').children('thead').children('tr');
        var headerVals = [];
        header.children('th').each(function() {
            headerVals.push($(this).html());
            if (!variables.hasOwnProperty($(this).html())) {
                var column = $(this).parent().children().index(this);
                example.find('tr').each(function() {
                    $(this).find("th:eq(" + column + ")").remove();
                    $(this).find("td:eq(" + column + ")").remove();
                })
            }
        });
        // add in any new values that may be missing
        for ( var key in variables) {
            if ($.inArray(key, headerVals) == -1) {
                header.append("" + key + "	");
                example.children('table').children('tbody').children('tr').each(function() {
                    var cell = $("	");
                    var input = $("#" + variables[key]).clone();
                    input.removeAttr('id');
                    input.removeAttr('style');
                    input.removeAttr('onchange');
                    input.val('');
                    if (input.is("input")) {
                        input.removeAttr('placeholder');
                    }
                    if (input.is("select")) {
                        input.find(">:first-child").remove();
                    }
                    cell.append(input);
                    $(this).append(cell);
                });
            }
        }
        ;
    });
    // rearrange our table
    var order = [];
    for ( var key in variables) {
        order.push(key);
    }
    var newOrder = [];
    examples.find('table').first().find('th').each(function() {
        newOrder.push(jQuery.inArray($(this).html(), order));
    });

    makeDynamic();
    // rename our scenario type if needed
    var cols = examples.children('table').children('thead').children('tr').children('th');
    if (cols.length == 0) {
        examples.parent().children('.green').children('.what').html("Scenario:");
        examples.remove();
        $(testEl).children('.addTable').hide();
    }
}
function addTable(el) {
    $(el).append("
" + "<input class='purple small' placeholder='Example Tags' />" + "
Examples:
" + "

" + "<button onclick='addDataRow(this)' class='ui-button ui-button-small'>Add Data Row</button>" + "
");
    $(el).children('.green').children('.what').html("Scenario Outline:");
    addDataRow($(el).children('.examples').last().children('table'));
}
function addDataRow(el) {
    var examples = $(el).parent();
    var body = examples.children('table').children('tbody');
    var cols = examples.children('table').children('thead').children('tr').children('th');
    var row = $("

");
    cols.each(function() {
        var cell = $("	");
        var input = $("#" + $(this).attr('inheritFrom')).clone();
        input.removeAttr('id');
        input.removeAttr('style');
        input.removeAttr('onchange');
        if (input.is("input")) {
            input.removeAttr('placeholder');
        }
        if (input.is("select")) {
            input.find(">:first-child").remove();
        }
        cell.append(input);
        row.append(cell);
    });
    body.append(row);
    makeDynamic();
}
function del(el) {
    $("#delete").dialog({
        buttons : {
            "Confirm" : function() {
                var tmp = $(el).parent().parent().parent()
                $(el).parent().remove();
                buildTable($(tmp));
                $('.required').each(function() {
                    checkRequired($(this));
                });
                $(this).dialog("close");
            },
            "Cancel" : function() {
                $(this).dialog("close");
            }
        }
    });

    $("#delete").dialog("open");
}
function edit(el) {
    var tmp = $(el).parent().parent().parent();
    var value = $(el).next().next().next().nextAll().html();
    fillStep($(el).next().next(), value);
    buildTable($(tmp));
}<commit_msg>Fixing inability to write new steps<commit_after>function makeDynamic() {
    // make our testSteps sortable
    $(".testSteps").sortable({
        stop : function(event, ui) {
            buildTable($(ui.item).parent().parent());
        }
    });
    // make the scenarios sortable
    $("#tests").sortable({
        handle : ".what"
    });
    // make the tables (example data) sortable
    $("tbody").sortable();
    // setup our new dropdowns using the chosen plugin
    $('select').each(function() {
        var placeholder = $(this).attr('placeholder');
        if ($(this).parent().is("td")) {
            placeholder = " ";
        }
        if ($(this).attr('multiple') == 'multiple') {
            $(this).chosen({
                placeholder_text_multiple : placeholder,
                width : 'auto',
                disable_search_threshold : 4,
                inherit_select_classes : true,
            });
        } else {
            $(this).chosen({
                placeholder_text_single : placeholder,
                width : $(this).width() + 30,
                disable_search_threshold : 4,
                inherit_select_classes : true,
            });
        }
    });
    // allow editing of an any span
    $('span.any').dblclick(function() {
        var input = $("<input type='text' class='small' />").keyup(resizeInput).each(resizeInput).blur(function() {
            if ($(this).val() == "") {
                $(this).parent().html("...");
            }
        });
        $(this).html(input);
    });
    // allow the toggling an opt span
    $('span.opt').dblclick(function() {
        if ($(this).css('opacity') > 0.5)
            $(this).css({
                opacity : 0.2
            });
        else
            $(this).css({
                opacity : 1
            });
    });
    // keep the size of our input fields under control
    $('input.small').each(function() {
        $(this).keyup(resizeInput).each(resizeInput);
    });
    // keep the size of our textareas under control
    $('textarea').keyup(function() {
        $(this).attr('rows', ($(this).val().split("\n").length || 1));
    });

    // mark required fields in red
    $('.required').keyup(function() {
        checkRequired($(this));
    });

    // initialize the delete dialog
    $("#delete").dialog({
        autoOpen : false,
        modal : true
    });
}

function checkRequired(element) {
    if (element.val() == "") {
        element.addClass("red");
    } else {
        element.removeClass("red");
    }
    // check to see if all required things are filled in
    if ($('.red:visible').length) {
        $('#exportFile').button("disable");
        $('#exportJIRA').button("disable");
    } else {
        $('#exportFile').button("enable");
        $('#exportJIRA').button("enable");
    }
}

function fillTag(el) {
    if (typeof tags !== 'undefined' && tags.length > 0) {
        $(el).attr('placeholder','Choose a Tag...')
        $(el).autocomplete({
            minLength : 0,
            source : tags,
            select : function(event, ui) {
                addTag(el, ui.item.value);
                return false;
            },
        }).click(function() {
            $(this).autocomplete("search", "");
        }).keyup(function(e) {
            if(e.keyCode == 32 || e.keyCode == 13){
                addTag(el);
            }
        }).blur(function(){
            addTag(el);
        });
    }
}
function addTag(el, tag) {
    if (tag == "" || tag === undefined ) {
        tag = $(el).val();
        if (tag == "") {
            return;
        }
    }
    // build the environment
    var span = $("");
    span.html(tag);
    span.addClass('tag');
    span.click(function(){
        $(this).remove();
    });
    $(el).after(span);
    $(el).val("");
}

function addScenario() {
    var scenario = $("
");
    var tags = $("<input class='purple small' placeholder='Scenario Tags'>");
    fillTag(tags);
    var holder = $("
");
    var what = $("");
    what.html("Scenario:");
    var title = $("<input class='green small required red' placeholder='Test Case Name' type='text' required>");
    var description = $("<textarea rows='1' placeholder='Test Case Description'>");
    var steps = $("
");
    var addSteps = $("<button onclick='addTestStep(this)' class='ui-button ui-button-small'>");
    addSteps.html("Add Test Step");
    var addTable = $("<button onclick='addDataTable(this)' class='addTable ui-button ui-button-small' style='display:none;'>");
    addTable.html("Add Data Table");
    var deleteButton = $("

");
    var linkButton = $("

");
    holder.append(what).append(" ").append(title).append($("
")).append(description);
    scenario.append(tags).append(holder).append(steps).append(addSteps).append(addTable).append(deleteButton);
    if (jiraOptions.project !== "") {
        scenario.append(linkButton);
    }
    $('#tests').append(scenario);
    makeDynamic();
}
function addTestStep(el) {
    var testStep = $("
");
    var editHolder = $("
");
    editHolder.append($(""));
    var deleteHolder = $("
");
    deleteHolder.append($(""));
    var select = $("<select class='blue' onchange='void(0);'>");
    select.append($("<option>"));
    select.append($("<option>Given</option>"));
    select.append($("<option>When</option>"));
    select.append($("<option>Then</option>"));
    testStep.append(editHolder).append(deleteHolder).append(select);
    $(el).parent().find('.testSteps').append(testStep);
    makeDynamic();
    fillStep(select, "");
}
function fillStep(el, initialVal) {
    $(el).next().nextAll().remove();
    var input = $("<input type='text' class='small' value='" + initialVal + "'/>");
    var autocompletes = [];
    for (var i = 0; i < testSteps.length; i++) {
        autocompletes.push({
            label : testSteps[i].string.stripTags(),
            value : testSteps[i].string,
            order : i
        });
    }
    input.autocomplete({
        minLength : 0,
        source : autocompletes,
        focus : function(event, ui) {
            input.val(ui.item.value.stripTags());
            return false;
        },
        select : function(event, ui) {
            fillVars(ui.item.order, $(this));
        },
    }).click(function() {
        $(this).autocomplete("search", "");
    }).blur(function() {
        createStep($(this));
    });
    $(el).next().after(input);
}

function createStep(el) {
    var newStep = $(el).val();
    var type = $(el).prev().prev();
    // Need to determine if this step matches something
    // Check each GWT, replace XXXX with (.*), and do a regex check
    // if any are a match, select it
    for (var i = 0; i < testSteps.length; i++) {
        var string = testSteps[i].string;
        var regex = string.replace(/(.*?)<\/span>/g, "($1)?");
        regex = regex.replace(/(.*?)<\/span>/g, "(.*?)");
        regex = regex.replace(/XXXX/g, "(.*)");
        regex = regex.stripTags();
        regex = "^" + regex + "$";
        var res = newStep.match(regex);
        if (res != null) {
            fillVars(i, el);
            var inputs = type.parent().children('input,select');
            for (var j = 1; j < res.length; j++) {
                if (res[j] == "XXXX") {
                    res[j] = "";
                }
                $(inputs).eq(j).val(res[j]);
                if ($(inputs).eq(j).is('select')) {
                    $(inputs).eq(j).trigger('chosen:updated');
                }
                buildTable(type.parent().parent().parent());
                makeDynamic();
            }
            return true;
        }
    }
    type.next().nextAll().remove();
    var newStepPieces = newStep.split(/<|>/);
    newStep = "";
    for (i = 0; i < newStepPieces.length; i++) {
        newStep += "" + newStepPieces[i] + "";
        if (newStepPieces[i + 1]) {
            newStep += "<input id='" + rand(10) + "' type='text' class='small' onchange='buildTable(this)' placeholder='<" + newStepPieces[i + 1] + ">' class='new' />";
            i++;
        }
    }
    type.parent().append(newStep);
    buildTable(type.parent().parent().parent());
    makeDynamic();
}

function fillVars(order, el) {
    var testStepString = testSteps[order].string;
    var testStepInputs = testSteps[order].inputs;
    var testStepPieces = testStepString.split("XXXX");
    var type = $(el).prev();
    type.nextAll().remove();
    for (var i = 0; i < testStepPieces.length; i++) {
        type.parent().append("" + testStepPieces[i] + "");
        if (testStepInputs[i] !== undefined) {
            var objID = rand(10);
            if (Object.prototype.toString.call(testStepInputs[i].value) === '[object Array]') {
                var sel = $("<select id='" + objID + "' type='" + testStepInputs[i].key + "' onchange='buildTable(this)' placeholder='<" + testStepInputs[i].key + ">'></select>");
                if (testStepInputs[i].key.endsWith("List")) {
                    sel.attr("multiple", "multiple");
                    sel.append("<option></option>");
                } else {
                    sel.append("<option><" + testStepInputs[i].key + "></option>");
                }
                for (var j = 0; j < testStepInputs[i].value.length; j++) {
                    sel.append("<option>" + testStepInputs[i].value[j] + "</option>");
                }
                type.parent().append(sel);
            } else {
                type.parent().append("<input id='" + objID + "' type='" + testStepInputs[i].value + "' class='small' onchange='buildTable(this)' placeholder='<" + testStepInputs[i].key + ">' />");
            }
        }
    }
    buildTable(type.parent().parent().parent());
    makeDynamic();
}
function addDataTable(el) {
    addTable($(el).parent());
    buildTable($(el).parent());
}
function buildTable(testEl) { // el should be the test element
    if (!$(testEl).hasClass('scenario')) {
        testEl = $(testEl).parent().parent().parent();
    }
    if (!$(testEl).hasClass('scenario')) {
        return false;
    }
    // add a table if needed
    if ($(testEl).find('.examples').length == 0) {
        addTable($(testEl));
        $(testEl).children('.addTable').show();
    }
    // get each variable from our test steps
    var variables = {};
    var scenario = $(testEl).children('.testSteps');
    scenario.children('.testStep').each(function() {
        $(this).children('input, select').each(function() {
            if ($(this).val() == null) {
                var placeholder = $(this).attr('placeholder')
                if (placeholder.startsWith("<") && placeholder.endsWith(">")) {
                    variables[placeholder.substring(1, placeholder.length - 1)] = $(this).attr('id');
                }
                return true;
            }
            if (Object.prototype.toString.call($(this).val()) === '[object Array]') {
                return true;
            }
            if ($(this).hasClass('ui-autocomplete-input')) {
                return true;
            }
            if ($(this).val() == "" && $(this).is("input")) {
                var placeholder = $(this).attr('placeholder')
                variables[placeholder.substring(1, placeholder.length - 1)] = $(this).attr('id');
                return true;
            }
            if ($(this).val().startsWith("<") && $(this).val().endsWith(">")) {
                var placeholder = $(this).val();
                variables[placeholder.substring(1, placeholder.length - 1)] = $(this).attr('id');
                return true;
            }
        });
    });
    var examples = scenario.parent().children('.examples');
    $(examples).each(function() {
        var example = $(this);
        // remove any columns that no longer exist in the variables
        var header = example.children('table').children('thead').children('tr');
        var headerVals = [];
        header.children('th').each(function() {
            headerVals.push($(this).html());
            if (!variables.hasOwnProperty($(this).html())) {
                var column = $(this).parent().children().index(this);
                example.find('tr').each(function() {
                    $(this).find("th:eq(" + column + ")").remove();
                    $(this).find("td:eq(" + column + ")").remove();
                })
            }
        });
        // add in any new values that may be missing
        for ( var key in variables) {
            if ($.inArray(key, headerVals) == -1) {
                header.append("" + key + "	");
                example.children('table').children('tbody').children('tr').each(function() {
                    var cell = $("	");
                    var input = $("#" + variables[key]).clone();
                    input.removeAttr('id');
                    input.removeAttr('style');
                    input.removeAttr('onchange');
                    input.val('');
                    if (input.is("input")) {
                        input.removeAttr('placeholder');
                    }
                    if (input.is("select")) {
                        input.find(">:first-child").remove();
                    }
                    cell.append(input);
                    $(this).append(cell);
                });
            }
        }
        ;
    });
    // rearrange our table
    var order = [];
    for ( var key in variables) {
        order.push(key);
    }
    var newOrder = [];
    examples.find('table').first().find('th').each(function() {
        newOrder.push(jQuery.inArray($(this).html(), order));
    });

    makeDynamic();
    // rename our scenario type if needed
    var cols = examples.children('table').children('thead').children('tr').children('th');
    if (cols.length == 0) {
        examples.parent().children('.green').children('.what').html("Scenario:");
        examples.remove();
        $(testEl).children('.addTable').hide();
    }
}
function addTable(el) {
    $(el).append("
" + "<input class='purple small' placeholder='Example Tags' />" + "
Examples:
" + "

" + "<button onclick='addDataRow(this)' class='ui-button ui-button-small'>Add Data Row</button>" + "
");
    $(el).children('.green').children('.what').html("Scenario Outline:");
    addDataRow($(el).children('.examples').last().children('table'));
}
function addDataRow(el) {
    var examples = $(el).parent();
    var body = examples.children('table').children('tbody');
    var cols = examples.children('table').children('thead').children('tr').children('th');
    var row = $("

");
    cols.each(function() {
        var cell = $("	");
        var input = $("#" + $(this).attr('inheritFrom')).clone();
        input.removeAttr('id');
        input.removeAttr('style');
        input.removeAttr('onchange');
        if (input.is("input")) {
            input.removeAttr('placeholder');
        }
        if (input.is("select")) {
            input.find(">:first-child").remove();
        }
        cell.append(input);
        row.append(cell);
    });
    body.append(row);
    makeDynamic();
}
function del(el) {
    $("#delete").dialog({
        buttons : {
            "Confirm" : function() {
                var tmp = $(el).parent().parent().parent()
                $(el).parent().remove();
                buildTable($(tmp));
                $('.required').each(function() {
                    checkRequired($(this));
                });
                $(this).dialog("close");
            },
            "Cancel" : function() {
                $(this).dialog("close");
            }
        }
    });

    $("#delete").dialog("open");
}
function edit(el) {
    var tmp = $(el).parent().parent().parent();
    var value = $(el).next().next().next().nextAll().html();
    fillStep($(el).next().next(), value);
    buildTable($(tmp));
}<|endoftext|>


<commit_before>// a thing that runs tests.
// Every "test" is also a harness.  If they do not have a harness,
// then they are attached to the defaut "global harness",
// which writes its results to stdout.

// TODO:
// - Bailout should stop running any tests.
// - "skip" in the test config obj should skip it.

module.exports = Harness
require("inherits")(Harness, require("events").EventEmitter)

var Results = require("tap-results")
  , TapProducer = require("tap-producer")
  , assert = require("tap-assert")

function Harness (Test) {
  if (!(this instanceof Harness)) return new Harness(Test)

  this._Test = Test
  this._plan = null
  this._children = []
  this._started = false

  this._testCount = 0
  this._planSum = 0

  this.results = new Results()

  var p = this.process.bind(this)
  this.process = function () {
    this._started = true
    process.nextTick(p)
  }

  this.output = new TapProducer()
  Harness.super.call(this)
}

// this function actually only gets called bound to
// the Harness object, and on process.nextTick.  Even if
// passed as an event handler, everything *else* will
// happen before it gets called.
Harness.prototype.process = function () {
  //console.error("harness process")
  // "end" can emit multiple times, so only actually move on
  // to the next test if the current one is actually over.
  // TODO: multiple in-process tests, if all are marked "async"
  if (this._current) {
    if (!this._current._ended) return
    // handle the current one before moving onto the next.
    this.childEnd(this._current)
  }
  var skip = true
  while (skip) {
    //console.error("checking for skips")
    var current = this._current = this._children.shift()
    if (current) {
      skip = current.conf.skip
      if (skip) {
        //console.error("add a failure for the skipping")
        this.results.add(assert.fail(current.conf.name
                                    ,{skip:true, diag:false}))
      }
    } else skip = false
  }

  // keep processing through skipped tests, instead of running them.
  if (current && this._bailedOut) {
    return this.process()
  }

  //console.error("got current?", !!current)
  if (current) {
    current.on("end", this.process)
    current.emit("ready")
    //console.error("emitted ready")
    //console.error("_plan", this._plan, this.constructor.name)
  } else {
    //console.error("Harness process: no more left.  ending")
    this.end()
  }
}

Harness.prototype.end = function () {
  //console.error("harness end", this.constructor.name)
  if (this._bailedOut) return

  // can't call .end() more than once.
  if (this._ended) {
    //console.error("adding failure for end calling")
    this.results.add(assert.fail("end called more than once"))
  }

  // see if the plan is completed properly, if there was one.
  if (this._plan !== null) {
    var total = this._testCount
    if (total !== this._plan) {
      this.results.add(assert.equal(total, this._plan, "test count != plan"))
    }
    this._plan = total
  }

  //console.error("setting ended true", this.constructor.name)
  this._ended = true
  this.emit("end")
}

Harness.prototype.plan = function (p) {
  //console.error("setting plan", new Error().stack)
  if (this._plan !== null) {
    //console.error("about to add failure for calling plan")
    return this.results.add(assert.fail("plan set multiple times"))
  }
  this._plan = p
  if (p === 0 || this.results.testsTotal) {
    this.end()
  }
}

Harness.prototype.childEnd = function (child) {
  //console.error("childEnd")
  this._testCount ++
  this._planSum += child._plan
  //console.error("adding set of child.results")
  this.results.addSet(child.results)
  this.emit("childEnd", child)
  // was this planned?
  if (this._plan === this._testCount) {
    //console.error("plan", [this._plan, this._testCount])
    return this.end()
  }
}

Harness.prototype.test = function test (name, conf, cb) {
  if (this._bailedOut) return

  if (typeof conf === "function") cb = conf, conf = null
  if (typeof name === "object") conf = name, name = null
  if (typeof name === "function") cb = name, name = null

  conf = conf || {}
  name = name || ""

  //console.error("making test", [name, conf, cb])

  // timeout: value in milliseconds. Defaults to 30s
  // Set to Infinity to have no timeout.
  if (isNaN(conf.timeout)) conf.timeout = 30000
  var t = new this._Test(this, name, conf)
  if (cb) {
    if (!isNaN(conf.timeout) && isFinite(conf.timeout)) {
      var timer = setTimeout(t.timeout.bind(t), conf.timeout)
      t.on("end", clearTimeout.bind(null, timer))
    }
    //console.error("attaching cb to ready event")
    t.on("ready", cb.bind(t, t))
    t.on("result", this.emit.bind(this))
  }
  return t
}

Harness.prototype.bailout = function (message) {
  message = message || ""
  //console.error("adding bailout message result")
  this.results.add({bailout: message})
  this._bailedOut = true
  this.emit("bailout", message)
}

Harness.prototype.add = function (child) {
  //console.error("adding child")
  this._children.push(child)
  if (!this._started) this.process()
}

// the tearDown function is *always* guaranteed to happen.
// Even if there's a bailout.
Harness.prototype.tearDown = function (fn) {
  this.on("end", fn)
}
<commit_msg>bubble up result events better<commit_after>// a thing that runs tests.
// Every "test" is also a harness.  If they do not have a harness,
// then they are attached to the defaut "global harness",
// which writes its results to stdout.

// TODO:
// - Bailout should stop running any tests.
// - "skip" in the test config obj should skip it.

module.exports = Harness
require("inherits")(Harness, require("events").EventEmitter)

var Results = require("tap-results")
  , TapProducer = require("tap-producer")
  , assert = require("tap-assert")

function Harness (Test) {
  if (!(this instanceof Harness)) return new Harness(Test)

  //console.error("Test in "+this.constructor.name, Test)

  this._Test = Test
  this._plan = null
  this._children = []
  this._started = false

  this._testCount = 0
  this._planSum = 0

  this.results = new Results()
  // emit result events on the harness.
  //this.results.on("result", function (res) {
  //  console.error("proxying result ev from res to harness")
  //  this.emit("result", res)
  //}.bind(this))
  var me = this
  this.results.on("result", this.emit.bind(this, "result"))

  var p = this.process.bind(this)
  this.process = function () {
    this._started = true
    process.nextTick(p)
  }

  this.output = new TapProducer()
  Harness.super.call(this)
}

// this function actually only gets called bound to
// the Harness object, and on process.nextTick.  Even if
// passed as an event handler, everything *else* will
// happen before it gets called.
Harness.prototype.process = function () {
  //console.error("harness process")
  // "end" can emit multiple times, so only actually move on
  // to the next test if the current one is actually over.
  // TODO: multiple in-process tests, if all are marked "async"
  if (this._current) {
    if (!this._current._ended) return
    // handle the current one before moving onto the next.
    this.childEnd(this._current)
  }
  var skip = true
  while (skip) {
    //console.error("checking for skips")
    var current = this._current = this._children.shift()
    if (current) {
      skip = current.conf.skip
      if (skip) {
        //console.error("add a failure for the skipping")
        this.results.add(assert.fail(current.conf.name
                                    ,{skip:true, diag:false}))
      }
    } else skip = false
  }

  // keep processing through skipped tests, instead of running them.
  if (current && this._bailedOut) {
    return this.process()
  }

  //console.error("got current?", !!current)
  if (current) {
    current.on("end", this.process)
    current.emit("ready")
    //console.error("emitted ready")
    //console.error("_plan", this._plan, this.constructor.name)
  } else {
    //console.error("Harness process: no more left.  ending")
    this.end()
  }
}

Harness.prototype.end = function () {
  //console.error("harness end", this.constructor.name)
  if (this._bailedOut) return

  // can't call .end() more than once.
  if (this._ended) {
    //console.error("adding failure for end calling")
    this.results.add(assert.fail("end called more than once"))
  }

  // see if the plan is completed properly, if there was one.
  if (this._plan !== null) {
    var total = this._testCount
    if (total !== this._plan) {
      this.results.add(assert.equal(total, this._plan, "test count != plan"))
    }
    this._plan = total
  }

  //console.error("setting ended true", this.constructor.name)
  this._ended = true
  this.emit("end")
}

Harness.prototype.plan = function (p) {
  //console.error("setting plan", new Error().stack)
  if (this._plan !== null) {
    //console.error("about to add failure for calling plan")
    return this.results.add(assert.fail("plan set multiple times"))
  }
  this._plan = p
  if (p === 0 || this.results.testsTotal) {
    this.end()
  }
}

Harness.prototype.childEnd = function (child) {
  //console.error("childEnd")
  this._testCount ++
  this._planSum += child._plan
  //console.error("adding set of child.results")
  this.results.addSet(child.results)
  this.emit("childEnd", child)
  // was this planned?
  if (this._plan === this._testCount) {
    //console.error("plan", [this._plan, this._testCount])
    return this.end()
  }
}

Harness.prototype.test = function test (name, conf, cb) {
  if (this._bailedOut) return

  if (typeof conf === "function") cb = conf, conf = null
  if (typeof name === "object") conf = name, name = null
  if (typeof name === "function") cb = name, name = null

  conf = conf || {}
  name = name || ""

  //console.error("making test", [name, conf, cb])

  // timeout: value in milliseconds. Defaults to 30s
  // Set to Infinity to have no timeout.
  if (isNaN(conf.timeout)) conf.timeout = 30000
  var t = new this._Test(this, name, conf)
  if (cb) {
    if (!isNaN(conf.timeout) && isFinite(conf.timeout)) {
      var timer = setTimeout(t.timeout.bind(t), conf.timeout)
      t.on("end", clearTimeout.bind(null, timer))
    }
    //console.error("attaching cb to ready event")
    t.on("ready", cb.bind(t, t))
    // proxy the child results to this object.
    //t.on("result", function (res) {
    //  console.error("in harness, proxying result up")
    //  t.results.add(res)
    //})
  }
  return t
}

Harness.prototype.bailout = function (message) {
  message = message || ""
  //console.error("adding bailout message result")
  this.results.add({bailout: message})
  this._bailedOut = true
  this.emit("bailout", message)
}

Harness.prototype.add = function (child) {
  //console.error("adding child")
  this._children.push(child)
  if (!this._started) this.process()
}

// the tearDown function is *always* guaranteed to happen.
// Even if there's a bailout.
Harness.prototype.tearDown = function (fn) {
  this.on("end", fn)
}
<|endoftext|>


<commit_before>//
//   # Parser
//
//   A monadic LL(infinity) parser.
//
//        var alpha = _.Parser.regexp(/^[a-zA-Z]+/),
//            number = _.Parser.regexp(/^[\+\-]?\d+(\.\d+)?/),
//            expr = alpha.orElse(number);
//        expr.parse('1.1');
//
//   * `chain(f)` - Monadic flatMap/bind
//   * `also(f)` - FlatMap/bind with concatenation of results
//   * `many` - Yield array of results
//   * `map(f)` - Functor map
//   * `orElse(a)` - Default parser or else try alternative
//   * `skip` - Skip the parser
//   * `parse` - Executes parser
//
var Parser = tagged('Parser', ['run']);

//
//  ### of(x)
//
//  Creates a parser that contains a successful value.
//
Parser.of = function(a) {
    return Parser(function() {
        return Tuple4(a, 0, Attempt.of([]), Option.None);
    });
};

//
//  ### empty()
//
//  Creates a parser that contains a empty value.
//
Parser.empty = function() {
    return Parser(function(a) {
        return Tuple4(a, 0, Attempt.of([]), Option.None);
    });
};

//
//  ### fail(x)
//
//  Creates a parser that contains a failed value.
//
Parser.fail = function(e) {
    return Parser(function(a, b) {
        return Tuple4(a, b, Attempt.Failure([e]), Option.of([e]));
    });
};

//
//  ### success(x)
//
//  Creates a parser that contains a successful value.
//
Parser.success = function(s) {
    return Parser(function(a, b) {
        return Tuple4(a, b, Attempt.of(s), Option.None);
    });
};

//
//  ### put(x)
//
Parser.put = function(a) {
    return Parser(function() {
        return a;
    });
};

//
//  ### regexp(x)
//
//  Parser that expects the stream to match the given regex.
//
Parser.regexp = function(a) {
    return Parser(function(stream, index, attempt, possibleFailure) {
        var value = stream.slice(index),
            match = a.exec(value),
            result;
        if(match) {
            result = match[0];
            return Tuple4(stream, index + result.length, Attempt.of([result]), possibleFailure);
        } else {
            return Tuple4(stream, index, Attempt.Failure([[value, index]]), possibleFailure);
        }
    });
};

//
//  ### string(x)
//
//  Parser that expects to find a string, and will yield the same.
//
Parser.string = function(a) {
    var length = a.length;
    return Parser(function(stream, index, attempt, possibleFailure) {
        var value = stream.slice(index, index + length);
        if (value === a) {
            return Tuple4(stream, index + length, Attempt.of([value]), possibleFailure);
        } else {
            return Tuple4(stream, index, Attempt.Failure([[value, index]]), possibleFailure);
        }
    });
};

//
//  ### chain(f)
//
//  Expects another Parser to follow parser, and yields the result of
//  another Parser.
//
Parser.prototype.chain = function(f) {
    var env = this;
    return Parser(function(stream, index, attempt, possibleFailure) {
        var outcome = env.run(stream, index, attempt, possibleFailure);
        return outcome._3.fold(
            function(x) {
                var a = f(outcome._1, outcome._2, outcome._3, outcome._4);
                return a.run(outcome._1, outcome._2, outcome._3, outcome._4);
            },
            function() {
                return Tuple4(outcome._1, outcome._2, outcome._3, outcome._4);
            }
        );
    });
};

//
//  ### also(f)
//
//  Expects another Parser to follow parser, and concatenates the result of
//  both Parser results.
//
Parser.prototype.also = function(f) {
    var env = this;
    return Parser(function(stream, index, attempt, possibleFailure) {
        var outcome = env.run(stream, index, attempt, possibleFailure);
        return outcome._3.fold(
            function(x) {
                var a = f(outcome._1, outcome._2, outcome._3, outcome._4);
                var b = a.run(outcome._1, outcome._2, outcome._3, outcome._4);
                return b._3.fold(
                    function(y) {
                        var c = Attempt.of([squishy.concat(x[0], y)]);
                        return Tuple4(b._1, b._2, c, b._4);
                    },
                    function() {
                        return b;
                    }
                );
            },
            function() {
                return Tuple4(outcome._1, outcome._2, outcome._3, outcome._4);
            }
        );
    });
};

//
//  ### many()
//
//  Expects parser zero or more times, and yields an array of the results.
//
Parser.prototype.many = function() {
    var env = this,
        recursive = function(stream) {
            return function rec(index, attempt, values) {
                var outcome = env.run(stream, index, attempt, Option.None);
                return outcome._3.fold(
                    function(x) {
                        var y = squishy.concat(values, x);
                        return rec(outcome._2, outcome._3, y);
                    },
                    function() {
                        return Tuple3(index, values, outcome._3.fold(
                            constant(outcome._3),
                            function(x) {
                                return outcome._4.fold(
                                    function(y) {
                                        return Attempt.Failure(y);
                                    },
                                    function() {
                                        return Attempt.Failure(x);
                                    }
                                );
                            }
                        ));
                    }
                );
            };
        };
    return Parser(function(stream, index, attempt) {
        var outcome = recursive(stream)(index, attempt, []),
            possibleFailure = outcome._3.fold(
                Option.empty,
                Option.of
            );
        return Tuple4(stream, outcome._1, Attempt.of([outcome._2]), possibleFailure);
    });
};

//
//  ### map(f)
//
//  Transforms the output of parser with the given function.
//
Parser.prototype.map = function(f) {
    return this.chain(function(stream, index, attempt, possibleFailure) {
        var x = f(attempt.value);
        return Parser.put(Tuple4(stream, index, Attempt.of(x), possibleFailure));
    });
};

//
//  ### orElse(a)
//
Parser.prototype.orElse = function(a) {
    var env = this;
    return Parser(function(stream, index, attempt, possibleFailure) {
        var outcome = env.run(stream, index, attempt, possibleFailure);
        return outcome._3.fold(
            function() {
                return outcome;
            },
            function() {
                var possible = a.run(stream, index, attempt, possibleFailure);
                return possible._3.fold(
                    function() {
                        return Tuple4(possible._1, possible._2, possible._3, possible._4);
                    },
                    function() {
                        return Tuple4(stream, index, outcome._3, outcome._4);
                    }
                );
            }
        );
    });
};

//
//  ### skip(a)
//
//  Returns a new parser which tries parser, and if it fails uses otherParser.
//
Parser.prototype.skip = function(a) {
    return this.chain(function(stream, index, attempt, possibleFailure) {
        return a.chain(function() {
            return Parser(function(stream, index, _, d) {
                return Tuple4(stream, index, attempt, possibleFailure);
            });
        });
    });
};

//
//  ### parse(stream)
//
//  Executes the parser with the given stream.
//
Parser.prototype.parse = function(stream) {
    var result = this.skip(eof).run(stream, 0, Attempt.of([]), Option.None);
    return result._3.fold(
        constant(result._3),
        function(x) {
            return result._4.fold(
                function(y) {
                    return Attempt.Failure(y);
                },
                constant(result._3)
            );
        }
    );
};

//
//  ### eof()
//
//  Expects the end of the stream.
//
var eof = Parser(function(stream, index, attempt, possibleFailure) {
    var outcome = index <= stream.length ? attempt : Attempt.Failure(['EOF', index]);
    return Tuple4(stream, index, outcome, possibleFailure);
});

//
//  ## isParser(a)
//
//  Returns `true` if `a` is `Parser`.
//
var isParser = isInstanceOf(Parser);

//
//  ### Fantasy Overload
//
fo.unsafeSetValueOf(Parser.prototype);

//
//  append methods to the squishy environment.
//
squishy = squishy
    .property('Parser', Parser)
    .property('isParser', isParser)
    .method('chain', isParser, function(a, b) {
        return a.chain(b);
    })
    .method('map', isParser, function(a, b) {
        return a.map(b);
    });
<commit_msg>Removing unwanted code.<commit_after>//
//   # Parser
//
//   A monadic LL(infinity) parser.
//
//        var alpha = _.Parser.regexp(/^[a-zA-Z]+/),
//            number = _.Parser.regexp(/^[\+\-]?\d+(\.\d+)?/),
//            expr = alpha.orElse(number);
//        expr.parse('1.1');
//
//   * `chain(f)` - Monadic flatMap/bind
//   * `also(f)` - FlatMap/bind with concatenation of results
//   * `many` - Yield array of results
//   * `map(f)` - Functor map
//   * `orElse(a)` - Default parser or else try alternative
//   * `skip` - Skip the parser
//   * `parse` - Executes parser
//
var Parser = tagged('Parser', ['run']);

//
//  ### of(x)
//
//  Creates a parser that contains a successful value.
//
Parser.of = function(a) {
    return Parser(function() {
        return Tuple4(a, 0, Attempt.of([]), Option.None);
    });
};

//
//  ### empty()
//
//  Creates a parser that contains a empty value.
//
Parser.empty = function() {
    return Parser(function(a) {
        return Tuple4(a, 0, Attempt.of([]), Option.None);
    });
};

//
//  ### fail(x)
//
//  Creates a parser that contains a failed value.
//
Parser.fail = function(e) {
    return Parser(function(a, b) {
        return Tuple4(a, b, Attempt.Failure([e]), Option.of([e]));
    });
};

//
//  ### success(x)
//
//  Creates a parser that contains a successful value.
//
Parser.success = function(s) {
    return Parser(function(a, b) {
        return Tuple4(a, b, Attempt.of(s), Option.None);
    });
};

//
//  ### put(x)
//
Parser.put = function(a) {
    return Parser(function() {
        return a;
    });
};

//
//  ### regexp(x)
//
//  Parser that expects the stream to match the given regex.
//
Parser.regexp = function(a) {
    return Parser(function(stream, index, attempt, possibleFailure) {
        var value = stream.slice(index),
            match = a.exec(value),
            result;
        if(match) {
            result = match[0];
            return Tuple4(stream, index + result.length, Attempt.of([result]), possibleFailure);
        } else {
            return Tuple4(stream, index, Attempt.Failure([[value, index]]), possibleFailure);
        }
    });
};

//
//  ### string(x)
//
//  Parser that expects to find a string, and will yield the same.
//
Parser.string = function(a) {
    var length = a.length;
    return Parser(function(stream, index, attempt, possibleFailure) {
        var value = stream.slice(index, index + length);
        if (value === a) {
            return Tuple4(stream, index + length, Attempt.of([value]), possibleFailure);
        } else {
            return Tuple4(stream, index, Attempt.Failure([[value, index]]), possibleFailure);
        }
    });
};

//
//  ### chain(f)
//
//  Expects another Parser to follow parser, and yields the result of
//  another Parser.
//
Parser.prototype.chain = function(f) {
    var env = this;
    return Parser(function(stream, index, attempt, possibleFailure) {
        var outcome = env.run(stream, index, attempt, possibleFailure);
        return outcome._3.fold(
            function(x) {
                var a = f(outcome._1, outcome._2, outcome._3, outcome._4);
                return a.run(outcome._1, outcome._2, outcome._3, outcome._4);
            },
            function() {
                return Tuple4(outcome._1, outcome._2, outcome._3, outcome._4);
            }
        );
    });
};

//
//  ### also(f)
//
//  Expects another Parser to follow parser, and concatenates the result of
//  both Parser results.
//
Parser.prototype.also = function(f) {
    var env = this;
    return Parser(function(stream, index, attempt, possibleFailure) {
        var outcome = env.run(stream, index, attempt, possibleFailure);
        return outcome._3.fold(
            function(x) {
                var a = f(outcome._1, outcome._2, outcome._3, outcome._4);
                var b = a.run(outcome._1, outcome._2, outcome._3, outcome._4);
                return b._3.fold(
                    function(y) {
                        var c = Attempt.of([squishy.concat(x[0], y)]);
                        return Tuple4(b._1, b._2, c, b._4);
                    },
                    function() {
                        return b;
                    }
                );
            },
            function() {
                return Tuple4(outcome._1, outcome._2, outcome._3, outcome._4);
            }
        );
    });
};

//
//  ### many()
//
//  Expects parser zero or more times, and yields an array of the results.
//
Parser.prototype.many = function() {
    var env = this,
        recursive = function(stream) {
            return function rec(index, attempt, values) {
                var outcome = env.run(stream, index, attempt, Option.None);
                return outcome._3.fold(
                    function(x) {
                        var y = squishy.concat(values, x);
                        return rec(outcome._2, outcome._3, y);
                    },
                    function(x) {
                        return Tuple3(index, values, outcome._4.fold(
                            function(y) {
                                return Attempt.Failure(y);
                            },
                            function() {
                                return Attempt.Failure(x);
                            }
                        ));
                    }
                );
            };
        };
    return Parser(function(stream, index, attempt) {
        var outcome = recursive(stream)(index, attempt, []),
            possibleFailure = outcome._3.fold(
                Option.empty,
                Option.of
            );
        return Tuple4(stream, outcome._1, Attempt.of([outcome._2]), possibleFailure);
    });
};

//
//  ### map(f)
//
//  Transforms the output of parser with the given function.
//
Parser.prototype.map = function(f) {
    return this.chain(function(stream, index, attempt, possibleFailure) {
        var x = f(attempt.value);
        return Parser.put(Tuple4(stream, index, Attempt.of(x), possibleFailure));
    });
};

//
//  ### orElse(a)
//
Parser.prototype.orElse = function(a) {
    var env = this;
    return Parser(function(stream, index, attempt, possibleFailure) {
        var outcome = env.run(stream, index, attempt, possibleFailure);
        return outcome._3.fold(
            function() {
                return outcome;
            },
            function() {
                var possible = a.run(stream, index, attempt, possibleFailure);
                return possible._3.fold(
                    function() {
                        return Tuple4(possible._1, possible._2, possible._3, possible._4);
                    },
                    function() {
                        return Tuple4(stream, index, outcome._3, outcome._4);
                    }
                );
            }
        );
    });
};

//
//  ### skip(a)
//
//  Returns a new parser which tries parser, and if it fails uses otherParser.
//
Parser.prototype.skip = function(a) {
    return this.chain(function(stream, index, attempt, possibleFailure) {
        return a.chain(function() {
            return Parser(function(stream, index, _, d) {
                return Tuple4(stream, index, attempt, possibleFailure);
            });
        });
    });
};

//
//  ### parse(stream)
//
//  Executes the parser with the given stream.
//
Parser.prototype.parse = function(stream) {
    var result = this.skip(eof).run(stream, 0, Attempt.of([]), Option.None);
    return result._3.fold(
        constant(result._3),
        function(x) {
            return result._4.fold(
                function(y) {
                    return Attempt.Failure(y);
                },
                constant(result._3)
            );
        }
    );
};

//
//  ### eof()
//
//  Expects the end of the stream.
//
var eof = Parser(function(stream, index, attempt, possibleFailure) {
    var outcome = index <= stream.length ? attempt : Attempt.Failure(['EOF', index]);
    return Tuple4(stream, index, outcome, possibleFailure);
});

//
//  ## isParser(a)
//
//  Returns `true` if `a` is `Parser`.
//
var isParser = isInstanceOf(Parser);

//
//  ### Fantasy Overload
//
fo.unsafeSetValueOf(Parser.prototype);

//
//  append methods to the squishy environment.
//
squishy = squishy
    .property('Parser', Parser)
    .property('isParser', isParser)
    .method('chain', isParser, function(a, b) {
        return a.chain(b);
    })
    .method('map', isParser, function(a, b) {
        return a.map(b);
    });
<|endoftext|>