$.prototype.addInput = function(sType, sName, sValue, aoEvents) {
	aoEvents = aoEvents || [];
	let $Input = $('<input>', {type: sType, name: sName, value: sValue}).data('old_value', sValue);
	$.each(aoEvents, (iIndex, aoEvent) => {
		$Input.on(aoEvent.on, aoEvent.callback);
	});
	return $(this).append($Input);
};

$.prototype.addButton = function(sIcon, sText, sName, fOnClick, sClass)
{
	sText = sText || '';
	sClass = sClass || '';
	var $Btn = $('<button>', {name: sName, 'class':sClass})
		.addIcon('fa-'+sIcon, (sText != ''))
		.append(sText)
		.click(fOnClick);

	return $(this).append($Btn);
};

$.prototype.addIcon = function(sIcon, bMargin, sStyle)
{
	bMargin = bMargin || false;
	sStyle = sStyle || '';
	return $(this).append($('<i>', {'class':'fa'+sStyle+' '+sIcon+(bMargin?' push':'')}));
};

$.prototype.defaultVal = function(sDefaultValue)
{
	$(this)
		.data('default_value', sDefaultValue)
		.val(sDefaultValue)
		.addClass('defaultText')
		.focus(function()
		{
			var $This = $(this);
			if($This.val() == $This.data('default_value')) $This.val('').removeClass('defaultText');
		})
		.blur(function()
		{
			var $This = $(this);
			if($This.val() == '') $This.val($This.data('default_value')).addClass('defaultText');
		});
};

$.prototype.checkForm = function(sSelector)
{
	sSelector = sSelector || 'input[type="text"], textarea';
	var $This = $(this);
	var bOk = true;
	$This.find(sSelector).each(function()
	{
		$This = $(this);
		bOk = bOk && $This.val()!='' && $This.val()!=$This.data('default_value');
	});
	return bOk;
};

$.prototype.cascadingDown = function(sDuration)
{
	return $(this).slideDown(sDuration, function(){$(this).next().cascadingDown(sDuration);});
};

$.prototype.hoverSwap = function(sDefault, sHover)
{
	return $(this)
		.data('default', sDefault)
		.data('hover', sHover)
		.hover(function(){
			var	$This = $(this),
				sHover = $This.data('hover');
				sDefault = $This.data('default');

			if(sDefault!='' && sHover != '') {
				$This.fadeOut('fast', function() {
					var $This = $(this);
					$This.text((sDefault==$This.text())?sHover:sDefault).fadeIn('fast');
			    });
			}
		})
		.text(sDefault);
};

$.prototype.onSwipe = function(fOnStart, fOnMove, fOnEnd){
	return $(this)
		.on('dragstart', (e) => {
			e.preventDefault();
		})
		.on('mousedown touchstart', (e) => {
			var $This = $(this);
			var oPos = getDragPosition(e);
			$This.data('x-start', oPos.x);
			$This.data('y-start', oPos.y);
			$This.data('x-move', oPos.x);
			$This.data('y-move', oPos.y);
			$This.data('moving', true).addClass('moving');
			fOnStart({
				xStart: $This.data('x-start'),
				yStart: $This.data('y-start')
			});
		})
		.on('touchmove mousemove', (e) => {
			var $This = $(this);
			if($This.data('moving')) {
				var oPos = getDragPosition(e);
				$This.data('x-move', oPos.x);
				$This.data('y-move', oPos.y);
				fOnMove({
					xStart: $This.data('x-start'),
					yStart: $This.data('y-start'),
					xMove: $This.data('x-move'),
					yMove: $This.data('y-move')
				});
			}
		})
		.on('mouseup mouseleave touchend', (e) => {
			var $This = $(this);
			if($This.data('moving')) {
				$This.data('moving', false).removeClass('moving');
				fOnEnd({
					xStart: $This.data('x-start'),
					yStart: $This.data('y-start'),
					xEnd: $This.data('x-move'),
					yEnd: $This.data('y-move')
				});
			}
		});
};