(function ($) {
  $.fn.observable = function (obj, opts) {
    opts = opts || {}
    var opts = {
      bind: opts.bind || 'ob',
      attr: opts.attr || 'app-bind',
      recursive: opts.recursive == undefined?true:opts.recursive
    }
    var o = $(this);
    if (opts.recursive) $('*').each(function () {$(this)._observable(obj, opts)});
    return this;
  },

  $.fn._observable = function (obj, opts) {
    var o = $(this), data = false, e, i, t;
    if (o.attr && o.attr(opts.attr)) {
      try {
        data = $.parseJSON("{" + o.attr(opts.attr) + "}");
      } catch (e) {}
      if (data) {
        for (var key in data) {
          switch (key) {
            case 'bind':
              e = data.bind.split('.');
              if (!obj[opts.bind]) obj[opts.bind] = {};
              t = obj[opts.bind];
              for (i = 0; i < (e.length - 1); i++) {
                if (!t[e[i]]) t[e[i]] = {}; t = t[e[i]];
              }
              t[e[e.length - 1]] = o;
              break;
            case 'click':
            case 'change':
            case 'submit':
            case 'dblclick':
            case 'mouseover':
            case 'mouseout':
              if (typeof data[key] == "function") o.click(data[key]);
              else o.click(obj[data[key]])
              break;
            case 'data':
              if (typeof data.data == "object") {
                for (var key2 in data.data) o.data(key2, data.data[key2]);
              } else o.data('data', data.data);
              break;
          }
        }
      }
    }
    return this;
  }

  $.queryStringParam = function (param) {
    var loc = location.search.substring(1, location.search.length);
    var param_value = false;
    var params = loc.split("&");
    for (i=0; i<params.length;i++) {
      param_name = params[i].substring(0,params[i].indexOf('='));
      if (param_name == param) {
          param_value = params[i].substring(params[i].indexOf('=')+1)
      }
    }
    if (param_value) {
      return unescape(param_value);
    }
    else {
      return false; //Here determine return if no parameter is found
    }
  }

  $.redirectTo = function (uri) {window.location.href = uri || window.location.href}

  $.cookie = function (name, value, opts) {
    if (value == undefined) {
	var nameEQ = name + "=";
	var ca = document.cookie.split(';');
	for(var i=0;i < ca.length;i++) {
 	  var c = ca[i];
	  while (c.charAt(0)==' ') c = c.substring(1,c.length);
	  if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
	}
	return null;
    } else {
      opts = opts || {};
      if (value == null || value === "") {value = ""; opts = {days: -1}}
      var ca = name + "=" + escape(value);
      if (opts.expires) ca+= "; expires=" + opts.expires;
      else if (opts.days) ca+= "; expires=" + new Date().setDate(opts.days).toGMTString();
      if (opts.path) ca+="; path=" + opts.path;
      if (opts.domain) ca+="; domain=" + opts.domain;
      if (opts.secure) ca+="; secure=" + opts.secure;
      document.cookie = ca;
    }
    return this;
  }

  $.browser.user = {
    timeOffset: new Date().getTimezoneOffset(),
    languageFull: navigator.language||navigator.userLanguage,
    language: (navigator.language||navigator.userLanguage).substr(0,2)
  }

  $.fn.realWidth = function () {
    var o = $(this);
    return o.width() + parseInt(o.css('padding-left')) + parseInt(o.css('padding-right'));
  }

  $.fn.realHeight = function () {
    var o = $(this);
    return o.height() + parseInt(o.css('padding-top')) + parseInt(o.css('padding-bottom'));
  }
})(jQuery);

Number.prototype.doubleChars = function () {
  if (this < 10) return '0' + this;
  return this;
}

