jQuery.ajaxSetup( {
	cache:false
} );

jQuery.extend({
	getAll: function( params, callback ) {
		return jQuery.get( '/SdfAjax/Json/all.json', params, callback, 'json' );
	},
	postJSON: function( url, data, callback ) 
	{
		if ( typeof data == "undefined" ) {
			data = {};
		}
		return jQuery.post( url, data, callback, 'json' );
	}
});

jQuery.extend({
    Q: window.location.search.length <= 1 ? {}
        : function(a){
            var i = a.length, 
                r = /%25/g,  // Ensure '%' is properly represented 
                h = {};      // (Safari auto-encodes '%', Firefox 1.5 does not)
            while(i--) {
                var p = a[i].split('=');
                h[ p[0] ] = r.test( p[1] ) ? decodeURIComponent( p[1] ) : p[1];
            }
            return h;
        }(window.location.search.substr(1).split('&'))
});


function hideMessage()
{
   $('#js_message').css( 'visibility', 'hidden' ).text('').css('color', 'black');
}

var SHADOW_DELETE = 2;
var SHADOW_SET = 1;

function createMessage(text, color, timeToShow, shadow)
{
	if ( shadow == SHADOW_SET ) {
		if ( $('#js_shadow').length == 0 ) {
			$('body').prepend('<div id="js_shadow" style="display:none"></div>');
		}
		$('#js_shadow').css('display', '');
	}
	else if ( shadow == SHADOW_DELETE ) {
		$('#js_shadow').css('display', 'none');
	}
	if ( ! color ) {
		color = 'Red';
	}
	if ( ! timeToShow ) {
		timeToShow = 3000;
	}

	if ( $('#js_message').length == 0 ) {
		$('body').prepend('<div id="js_message"></div>');
		$('#js_message').click(hideMessage);
	}

	$('#js_message').css( 'visibility', 'visible' ).html(text).css('color', color);
	if ( timeToShow > 0 ) {
		setTimeout( "hideMessage()", timeToShow );
	}
}

var ajaxUrls = new Object();

function loadAjaxWidget( id )
{
	$.post( ajaxUrls[id], function( html ) {
		$('#widget'+id).html( html );
	} );
}

var sdfModeCursor = 'cursor';
var sdfModeSrcRight = 'src_right';

function sdfContextMenu( htmlSrc, mode, event )
{

	if ( $('#ctxMenu').length ) {
		menu = $('#ctxMenu');
	}
	else
	{
		menu = $("<div id='ctxMenu'></div>")
			.hide()
			.css({position:"absolute", zIndex:"500"})
			.appendTo("body")
			.bind("click", function(e) {
				e.stopPropagation();
			});
	}

	menu.html( $(htmlSrc).html() );

	if ( mode == sdfModeSrcRight )
	{
		var srcElement = event.target ? event.target : event.srcElement;
		menu.css( {"left":$(srcElement).offset().left+$(srcElement).width(), "top":$(srcElement).offset().top} ).show();
	}
	else // sdfModeCursor
	{
		if ( event.pageX ) {
			menu.css( {"left":event.pageX, "top":event.pageY} ).show();
		}
		else {
			menu.css( {"left":event.clientX, "top":event.clientY + document.body.scrollTop} ).show();
		}
	}

	$(document).one("click", function() {menu.hide()});
	if ( event.stopPropagation ) {
		event.stopPropagation();
	}
	else {
		event.cancelBubble = true;
	}
	return false;
}

function sdfContextMenuHide()
{
	if ( $('#ctxMenu').length ) {
		menu = $('#ctxMenu');
		menu.hide();
	}
}

function sdfObjectJoinKeys( Obj, Glue )
{
	var s = '';
	for ( var i in Obj ) {
		s += ','+i;
	}
	if ( s != '' ) {
		s = s.substr(1);
	}
	return s;
}

jQuery.fn.inlineHint = function() {
	var hint = '';
	if ( arguments.length > 0 ) {
		hint = jQuery.trim(arguments[0]);
	}
	return this.each(function(){
		var x = jQuery(this);
		if ( hint != '' )
		{
			if ( this.value == x.attr('inline-hint') ) {
				this.value = '';
			}
			x.attr('inline-hint', hint);
		}
		if ( x.attr('inline-hint') )
		{
			if ( jQuery.trim(this.value) == '' || this.value == x.attr('inline-hint') )
			{
				x.addClass('inline-hint');
				this.value = this.getAttribute('inline-hint');
			}
			else {
				x.removeClass('inline-hint');
			}
			x.focus( jQuery.inlineHint.focus );
			x.blur( jQuery.inlineHint.blur );
		}
	});
}


jQuery.inlineHint = {
	init: function() {
		jQuery("[inline-hint]").inlineHint();
	},
	focus: function(ev) {
		var el = ev.target;
		if (el.value == el.getAttribute('inline-hint') )
		{
			el.value = '';
			jQuery(el).removeClass( 'inline-hint' );
		}
	},
	blur: function(ev) {
		var el = ev.target;
		if ( jQuery.trim(el.value) == '' || el.value == el.getAttribute('inline-hint') )
		{
			jQuery(el).addClass( 'inline-hint' );
			el.value = el.getAttribute( 'inline-hint' );
		}
	}
};

$(document).ready(function(){
	$.inlineHint.init();
});

jQuery.extend({

	textNodes: function( context, jQueryResult ) {
	// Set the correct context (if none is provided)
		context = context || document;
		jQueryResult = jQueryResult || true;
		var done = [];

		function bumsRunTree(elem)
		{
			var cur;
			if (elem.hasChildNodes())
			{
				for ( var i = 0; i < elem.childNodes.length; i++)
				{
					cur = elem.childNodes.item(i);
					name = cur.parentNode.nodeName.toUpperCase();
					if (	3 == cur.nodeType
						&& name != 'SCRIPT' && name != 'STYLE' && name != 'OPTION'
						&& $.trim(cur.nodeValue) != '' )
					{
						jQuery.merge( done, [cur] );
					}
					else if( null == cur.nodeValue ) {
						bumsRunTree(cur);
					}
				}
			}
		}

		bumsRunTree(context);

		return jQueryResult ? jQuery(done) : done;
	}

});

jQuery.fn.extend({
	textNodes: function()
	{
		var done = [];
		this.each( function() {
			jQuery.merge( done, jQuery.textNodes(this, false) );
		});
		return jQuery(done);
	}
});

jQuery.extend({

	absPos: function( el, notDocRel )
	{
		notDocRel = notDocRel || false;

		var SL = 0, ST = 0;
		var r = { x: el.offsetLeft - SL, y: el.offsetTop - ST };
		if (el.offsetParent)
		{
			if ( notDocRel && jQuery(el.offsetParent).css('position') == 'relative' ) {
				return r;
			}
		// глюк ослика: когда контейнер "relative", то почему-то оффсет контейнера прибавляется к офсету текущего элемента - вычитаем
			/*if ( $.browser.msie )
			{
				if (	jQuery(el).css('position') == 'static'
					&&	el.offsetParent && jQuery(el.offsetParent).css('position') == 'relative'
					&& el.offsetParent.offsetParent && jQuery(el.offsetParent.offsetParent).css('position') == 'relative' )
				{
					var x = el.offsetParent;
					while ( jQuery(x.offsetParent.offsetParent).css('position') == 'relative' ) {
						x = x.offsetParent;
					}
					r.x = r.x - x.offsetLeft;
				}
			}*/
			var tmp = jQuery.absPos(el.offsetParent, notDocRel);
			r.x += tmp.x;
			r.y += tmp.y;
		}
		return r;
	},

	composeUrl: function( url, params )
	{
		if (typeof params != "string") {
 			params = jQuery.param(params);
		}
	// append params to url
	// "?" + data or "&" + data (in case there are already params)
		return url + ((url.indexOf("?") > -1) ? "&" : "?") + params;
	}

});

jQuery.fn.extend({
	absPos: function( notDocRel )
	{
		var res = [], i = 0;
		notDocRel = notDocRel || false;
		this.each( function() {
			res[i++] = jQuery.absPos( this, notDocRel );
		});
		return i > 1 ? res : res[0];
	},

	/**
	 * Returns how many pixels the user has scrolled to the bottom (scrollTop).
	 * Works on containers with overflow: auto and window/document.
	 *
	 * @example $("#testdiv").scrollTop()
	 * @result 100
	 *
	 * @name scrollTop
	 * @type Number
	 * @cat Plugins/Dimensions
	 */
	/**
	 * Sets the scrollTop property and continues the chain.
	 * Works on containers with overflow: auto and window/document.
	 *
	 * @example $("#testdiv").scrollTop(10).scrollTop()
	 * @result 10
	 *
	 * @name scrollTop
	 * @param Number value A positive number representing the desired scrollTop.
	 * @type jQuery
	 * @cat Plugins/Dimensions
	 */
	scrollTop: function(val) {
		if ( val != undefined )
			return this.each(function() {
				if (this == window || this == document)
					window.scrollTo( $(window).scrollLeft(), val );
				else
					this.scrollTop = val;
			});

		if ( this[0] == window || this[0] == document )
			return self.pageYOffset ||
				$.boxModel && document.documentElement.scrollTop ||
				document.body.scrollTop;

		return this[0].scrollTop;
	},

	bindCheck: function ( EvtType, Validators, Handlers, Form, checkImmediately )
	{
		this.each( function() {
			var jEl = $( this );
			var field = Form.registerCheck( jEl, Validators, Handlers );
			if ( typeof checkImmediately != 'undefined' && checkImmediately ) {
				field.check();
			}
			evtTypes = EvtType.split( '|' );
			for ( var j = 0; j < evtTypes.length; j++ ) {
				jEl.bind( evtTypes[j], function() { field.check() } );
			}
		} );
	}

});

//{{{ Array.indexOf
/**
 * Добавляет метод indexOf для массивов в тех браузерах, где его нет
 */
if (!Array.prototype.indexOf)
{
  Array.prototype.indexOf = function(elt /*, from*/)
  {
    var len = this.length;

    var from = Number(arguments[1]) || 0;
    from = (from < 0)
         ? Math.ceil(from)
         : Math.floor(from);
    if (from < 0)
      from += len;

    for (; from < len; from++)
    {
      if (from in this &&
          this[from] === elt)
        return from;
    }
    return -1;
  };
}
//===========================================================================}}}
//{{{ RegExp.escape
/**
 * Расширяет системный класс RegExp
 * Добавляет метод для экранирования строк, которые внедряются в регулярное выражение
 */
RegExp.escape = function(text) {
  if (!arguments.callee.sRE) {
    var specials = [
      '/', '.', '*', '+', '?', '|',
      '(', ')', '[', ']', '{', '}', '\\'
    ];
    arguments.callee.sRE = new RegExp(
      '(\\' + specials.join('|\\') + ')', 'g'
    );
  }
  return text.replace(arguments.callee.sRE, '\\$1');
}

function sdfDebugMsg( Msg )
{
	if ( $('#DEBUG').length == 0 ) {
		$('<div id="DEBUG" style="position:absolute; left:10px; top:100px; width:200px; height:400px; overflow:auto; background-color:White; color:red; opacity:0.7; filter:alpha(opacity=70);"></div>')
		.appendTo( document.body );
	}
	$('#DEBUG').html( $('#DEBUG').html()+Msg+'<p>' );
}

function sdfConfirm( Content, PosEl )
{
	var jEl = PosEl.instanceOf ? PosEl.$el : $(PosEl);
	var absPos = jEl.absPos();
	$( Content ).appendTo( document.body )
		.css( {position:'absolute', left: absPos.x, top: absPos.y+jEl.height()} )
		.show();
}

function sdfConfirmWithCallback( Content, PosEl, YesCallback )
{
	$( Content ).find( '.yes' ).one( 'click', function() { YesCallback(); $(Content).hide(); } );
	sdfConfirm( Content, PosEl );
}

function sdfHandleJsonException( json )
{
	if ( ! json.ERROR ) {
		return false;
	}
	if ( $( '#bigBaraBoom' ).length ) {
		$( '#bigBaraBoom' ).html( '<h4>'+json.ERROR+'</h4><pre>'+json.ERROR_INFO+'</pre>' );
	}
	else {
		createMessage( '<h4>'+json.ERROR+'</h4><pre>'+json.ERROR_INFO+'</pre>', 'Red' );
	}
	return true;
}

function startTutorial()
{
	$('<link rel="stylesheet" href="/i/lightbox/lightbox.css" type="text/css" media="screen" />').appendTo( $( 'head' ) );

	$( '<div id="lightBoxImages" style="display:none;"></div>' ).appendTo( document.body ).load( sdfUrlTo( 'BumsCommonC_Menu', 'tutor' ), function(){
		$( '#lightBoxImages a' ).lightboxStart();
	} )
}

function startWorkInit()
{
	var $menuMainHelp = $( '.menuMainHelp' );
	var $startWork = $( '#startWork' );
	var offset = $menuMainHelp.offset();
	$startWork.css( {left: '-9999px', top: offset.top+'px'} ).removeClass('hidden');
	var maxLeft = offset.left - $startWork.width() - 10;
	$startWork.css( 'left', '300px' ).animate( {left:maxLeft+'px'}, 3000 );
	setTimeout( function(){ $startWork.find( '.cancel' ).show(); }, 5000 );
}

function startWorkCancel()
{
	$.post( sdfUrlTo( 'BumsCommonC_Menu', 'startWorkCancel', '.json' ), {} );
	$( '#startWork' ).hide();
}

function sdfAjaxEncode( Data, Path )
{
	var s = '';
	var valS = '';
	var varS = '';
	if ( typeof( Data ) == 'function' ) {
		return null;
	}
	if ( typeof( Path ) == 'undefined' ) {
		Path = [];
	}
	if ( typeof( Data ) == 'object' )
	{
		for ( var i in Data )
		{
			Path.push( i );
			valS = sdfAjaxEncode( Data[i], Path );
			if ( valS !== null )
			{
				if ( s ) {
					s = s + '&';
				}
				s = s + valS;
			}
			Path.pop();
		}
		return s;
	}
	else
	{
		valS = encodeURIComponent( Data );
		varS = Path.length == 1 ? Path[0] : Path[0]+'['+Path.slice( 1 ).join( '][' )+']';
		return varS + '=' + valS;
	}
}

function sdfSavePref( Controller, Action, Pref, Value )
{
	if ( typeof( Pref ) == 'object' ) {
		$.post( sdfUrlTo( 'SdfCommonC_Pref', 'update', '.easy' ), sdfAjaxEncode( { ctrl:Controller, act:Action, data:Pref } ) );
	}
	else {
		$.post( sdfUrlTo( 'SdfCommonC_Pref', 'update', '.easy' ), sdfAjaxEncode( { ctrl:Controller, act:Action, name:Pref, value:Value } ) );
	}

}

//Simulates PHP's date function
Date.prototype.format = function(format) {
	var returnStr = '';
	var replace = Date.replaceChars;
	for (var i = 0; i < format.length; i++) {
		var curChar = format.charAt(i);
		if (replace[curChar])
			returnStr += replace[curChar].call(this);
		else
			returnStr += curChar;
	}
	return returnStr;
};

Date.replaceChars = {
	shortMonths: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
	longMonths: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
	shortDays: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
	longDays: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
	
	// Day
	d: function() { return (this.getDate() < 10 ? '0' : '') + this.getDate(); },
	D: function() { return Date.replace.shortDays[this.getDay()]; },
	j: function() { return this.getDate(); },
	l: function() { return Date.replace.longDays[this.getDay()]; },
	N: function() { return this.getDay() + 1; },
	S: function() { return (this.getDate() % 10 == 1 && this.getDate() != 11 ? 'st' : (this.getDate() % 10 == 2 && this.getDate() != 12 ? 'nd' : (this.getDate() % 10 == 3 && this.getDate() != 13 ? 'rd' : 'th'))); },
	w: function() { return this.getDay(); },
	z: function() { return "Not Yet Supported"; },
	// Week
	W: function() { return "Not Yet Supported"; },
	// Month
	F: function() { return Date.replace.longMonths[this.getMonth()]; },
	m: function() { return (this.getMonth() < 9 ? '0' : '') + (this.getMonth() + 1); },
	M: function() { return Date.replace.shortMonths[this.getMonth()]; },
	n: function() { return this.getMonth() + 1; },
	t: function() { return "Not Yet Supported"; },
	// Year
	L: function() { return "Not Yet Supported"; },
	o: function() { return "Not Supported"; },
	Y: function() { return this.getFullYear(); },
	y: function() { return ('' + this.getFullYear()).substr(2); },
	// Time
	a: function() { return this.getHours() < 12 ? 'am' : 'pm'; },
	A: function() { return this.getHours() < 12 ? 'AM' : 'PM'; },
	B: function() { return "Not Yet Supported"; },
	g: function() { return this.getHours() == 0 ? 12 : (this.getHours() > 12 ? this.getHours() - 12 : this.getHours()); },
	G: function() { return this.getHours(); },
	h: function() { return (this.getHours() < 10 || (12 < this.getHours() < 22) ? '0' : '') + (this.getHours() < 10 ? this.getHours() + 1 : this.getHours() - 12); },
	H: function() { return (this.getHours() < 10 ? '0' : '') + this.getHours(); },
	i: function() { return (this.getMinutes() < 10 ? '0' : '') + this.getMinutes(); },
	s: function() { return (this.getSeconds() < 10 ? '0' : '') + this.getSeconds(); },
	// Timezone
	e: function() { return "Not Yet Supported"; },
	I: function() { return "Not Supported"; },
	O: function() { return (this.getTimezoneOffset() < 0 ? '-' : '+') + (this.getTimezoneOffset() / 60 < 10 ? '0' : '') + (this.getTimezoneOffset() / 60) + '00'; },
	T: function() { return "Not Yet Supported"; },
	Z: function() { return this.getTimezoneOffset() * 60; },
	// Full Date/Time
	c: function() { return "Not Yet Supported"; },
	r: function() { return this.toString(); },
	U: function() { return this.getTime() / 1000; }
};

//{{{ cloneObj
/**
 * Клонирует объект
 * @author eugene
 * @since  29.01.2009 15:45:56
 */
function cloneObj( Obj ) 
{
	if( ! Obj || 'object' !== typeof Obj )  {
		return Obj;
	}
	var c = 'function' === typeof Obj.pop ? [] : {};
	var p, v;
	for ( p in Obj ) 
	{
		if( Obj.hasOwnProperty( p ) ) 
		{
			v = Obj[p];
			if ( v && 'object' === typeof v ) {
				c[p] = cloneObj( v );
			}
			else {
				c[p] = v;
			}
		}
	}
	return c;
}