﻿/// <reference path="jquery-1.4.1-vsdoc.js" />

String.prototype.shift = function(index) {
	return index < 0 ? this.substr(this.length + index) : this.substr(index);
};

Date.prototype.toEtag = function() {
	return this.getUTCFullYear()
		+ ('0' + (this.getUTCMonth() + 1)).shift(-2)
		+ ('0' + this.getUTCDate()).shift(-2)
		+ ('0' + this.getUTCHours()).shift(-2)
		+ ('0' + this.getUTCMinutes()).shift(-2)
		+ ('0' + this.getUTCSeconds()).shift(-2)
		+ ('00' + this.getUTCMilliseconds()).shift(-3);
};

Date.prototype.addMinutes = function(minutes) {
	return new Date(new Date(this).setMinutes(this.getMinutes() + minutes));
};

(function($) {
	var cache = {};

	// old regexp
	// /["']\\\/Date\((\d+)([\+\-]\d+)?\)\\\/["']/gi; 
	// /"\\\/(Date\(.*?\))\\\/"/gi;
	var dateRe = /\/Date\((\d+)([\+\-]\d+)?\)\//gi;

	var datesToDateObjects = function(obj) {
		for (p in obj) {
			if (typeof obj[p] === "string" && obj[p].search(dateRe) != -1)
				obj[p] = new Date(+obj[p].replace(dateRe, "$1"));
			if (typeof obj[p] === "object")
				obj[p] = datesToDateObjects(obj[p]);
		}

		return obj;
	}

	var base$parseJSON = $.parseJSON;

	$.extend({
		init: function() {
			var fn, context;

			for (var i = 0; i < arguments.length; i++)
				$.isFunction(arguments[i])
					? fn = arguments[i] : context = arguments[i];

			if (!fn)
				throw 'Initialize function isn\'t found.';


			if (arguments.length != 1 && !context)
				throw 'Context is undefined.';

			return fn.call(context = context || {}) || context;
		},
		sequencial: function(arr, fn) {
			var l = arr.length, seq = 0, callback = function() {
				seq != l ? fn.call(arr[seq++], callback) : null;
			};

			if (typeof l === 'number')
				callback();
		},
		cache: function(id, obj) {
			return cache[id] || (cache[id] = obj);
		},
		cookie: function(name, value, options) {
			if (typeof value != 'undefined') { // name and value given, set cookie
				options = options || {};

				if (value === null) {
					value = '';
					options.expires = -1;
				}

				var expires = '';

				if (options.expires && (typeof options.expires == 'number' || options.expires.toUTCString)) {
					var date;

					if (typeof options.expires == 'number') {
						date = new Date();
						date.setTime(date.getTime() + (options.expires * 24 * 60 * 60 * 1000));
					} else {
						date = options.expires;
					}

					expires = '; expires=' + date.toUTCString(); // use expires attribute, max-age is not supported by IE
				}

				// CAUTION: Needed to parenthesize options.path and options.domain
				// in the following expressions, otherwise they evaluate to undefined
				// in the packed version for some reason...
				var path = options.path ? '; path=' + (options.path) : '';
				var domain = options.domain ? '; domain=' + (options.domain) : '';
				var secure = options.secure ? '; secure' : '';

				document.cookie = [name, '=', encodeURIComponent(value), expires, path, domain, secure].join('');

				return value;
			} else {
				// only name given, get cookie
				if (document.cookie && document.cookie != '') {
					var cookies = document.cookie.split(';');

					for (var i = 0; i < cookies.length; i++) {
						var cookie = jQuery.trim(cookies[i]);

						// Does this cookie string begin with the name we want?
						if (cookie.substring(0, name.length + 1) == (name + '=')) {
							value = decodeURIComponent(cookie.substring(name.length + 1));
							break;
						}
					}
				}
				return value;
			}
		},
		storage: {
			get: function(name) {
				var data = $.cookie(name);

				return data ? JSON.parse(data) : null;
			},
			set: function(name, data, options) {
				return $.cookie(name, JSON.stringify(data), $.extend({ expires: 90, path: '/' }, options)) && data;
			},
			remove: function(name) {
				return $.cookie(name, null);
			}
		},
		parseJSON: function(data) {
			return datesToDateObjects(base$parseJSON(data));
		},
		window: (function() {
			var 
			self = this,
			onFocus = [],
			onBlur = []
			;

			self.focus = function(fn) {
				if ($.isFunction(fn)) {
					return onFocus.push(fn);
				}

				if (self.focused)
					return;

				for (var i in onFocus)
					onFocus[i]();

				self.focused = true;
			};

			self.blur = function(fn) {
				if ($.isFunction(fn))
					return onBlur.push(fn);

				if (!self.focused)
					return;

				for (var i in onBlur)
					onBlur[i]();

				self.focused = false;
			};

			self.focused = true;

			window.onfocus = self.focus;
			window.onblur = self.blur;

			return self;
		}).apply({})
	});

	var $text = $.fn.text;

	$.fn.extend({
		bindo: function(data, clone) {
			var self = typeof clone === 'boolean' && !clone
				? this : this.clone().removeClass('template');

			return self.find('*[bind]').add(self.filter('[bind]')).each(function() {
				var fn;
				eval('fn = function(data) { ' + $(this).attr('bind') + ';};');
				fn.call($(this), data);
			}).end().end();
		},
		store: function(prop, value) {
			return this.data('stored:' + prop, value);
		},
		restore: function(prop) {
			return this.data('stored:' + prop);
		},
		sequencial: function(fn) {
			$.sequential($.makeArray(this), fn);
		},
		text: function(text) {
			return typeof text !== "object" && text != null && $.browser.msie && $.browser.version < 8
				? $.each(this, function() { this.innerText = text; }) && this : $text.call(this, text);
		}
	});

	$.extend($.expr[':'], {
		'visible': function(e) {
			return (e.offsetWidth > 0 || e.offsetHeight > 0) && e.style.visibility != 'hidden';
		} /*,
		'in-view': function(e) {
		}*/
	});

	if ($.browser.msie && $.browser.version == 6) {
		jQuery.support.opacity = true;
	}
})(jQuery);
