(function () {
if (window.mm) return;
var d = document, ready = false, self = {
  basedir: (function (el) {
    return (el.nodeName == 'SCRIPT')
      ? el.src.replace(/\/[^\/]+$/, '')
      : arguments.callee(el.lastChild || el.previousSibling);
  })(d.body || d),
  
  has: function (obj, key) {
    if (arguments.length <= 1)
      return (typeof obj != 'undefined');
    return !!obj && obj.hasOwnProperty(key);
  },
  
  arr: function (obj) {
    for (var arr = [], i = 0, ix = obj.length; i < ix; i++)
      arr.push(obj[i]);
    return arr;
  },
  
  bind: function (fn) {
    var self = this;
    return function () {
      return fn.apply(self, [this].concat(self.arr(arguments)));
    };
  },
  
  each: function () {
    var args = this.arr(arguments);
    var fn   = args.pop();
    for (var items, i = 0; items = args[i]; i++) {
      if (this.has(items, 'length'))
        for (var key = 0, len = items.length; key < len; key++) {
          var value = items[key];
          if (fn.apply(this, (fn.length >= 2) ? [key, value] : [value]) === false)
            return;
        }
      else
        for (var key in items) if (this.has(items, key)) {
          var value = items[key];
          if (fn.apply(this, (fn.length >= 2) ? [key, value] : [value]) === false)
            return;
        }
    }
  },
  
  map: function () {
    var items = [];
    var args  = this.arr(arguments);
    var fn    = args.pop();
    this.each.apply(this, args.concat([function (key, value) {
      var item = fn.apply(this, (fn.length >= 2) ? [key, value] : [value]);
      if (this.has(item))
        items.push(item);
    }]));
    
    return items;
  },
  
  clone: function (obj, props) {
    var clone = this.has(obj, 'length') ? [] : {};
    this.each(obj, function (key, prop) {
      clone[key] = prop;
    });
    this.each(props, function (key, prop) {
      clone[key] = prop;
    });
    
    return clone;
  },
  
  extend: function (props) {
    var c = function () {};
    c.prototype = this;
    
    var obj = new c;
    this.each(props, function (key, prop) {
      obj[key] = prop;
    });
    obj.superclass = this;
    
    return obj;
  },
  
  use: function (src) {
    if (ready) {
      var el  = d.createElement('script');
      el.type = 'text/javascript';
      el.src  = src;
      d.getElementsByTagName('head')[0].appendChild(el);
    }
    else
      d.write('<script type="text/javascript" src="' + src + '"></script>');
  },
  
  ready: (function () {
    var _fn = [];
    var run = function () {
      ready = true;
      self.each(_fn, function (fn) { fn(); });
    };
    
    if (!!(window.attachEvent && !window.opera))
      (function () {
        try { d.documentElement.doScroll('left'); run(); }
        catch (err) { setTimeout(arguments.callee, 0); }
      })();
    else if (/webkit\/(\d+)/i.test(navigator.userAgent) && (RegExp.$1 < 525))
      var timer = setInterval(function () {
        if (/^(loaded|complete)$/.test(d.readyState))
          clearInterval(timer), run();
      }, 0);
    else
      d.addEventListener('DOMContentLoaded', run, false);
    
    return function (fn) {
      fn = this.bind(fn);
      if (ready)
        return fn();
      _fn.push(fn);
    };
  })(),
  
  location: function (url) {
    url = url || location.href;
    return (function (url, scheme, host, port, path, query, hash) {
      return {
        scheme: scheme,
        host:   host,
        port:   port,
        path:   path,
        query:  query,
        hash:   hash
      };
    }).apply(null, url.match(
      /^(https?):\/\/([^\/:]+):?([^\/]*)([^\?#]+)\??([^#]*)#?(.*)$/
    ));
  },
  
  localtime: function (date, format) {
    date = date || new Date;
    return {
      year:     date.getFullYear(),
      mon:      date.getMonth() + 1,
      day:      date.getDate(),
      hour:     date.getHours(),
      min:      date.getMinutes(),
      sec:      date.getSeconds(),
      time:     date.getTime(),
      format:   format,
      toString: function (format) {
        var self = this;
        if (format = format || self.format)
          return format.replace(/%([YmdHMS])/g, function (str, m) {
            switch (m) {
              case 'Y': return self.year;
              case 'm': return (self.mon  < 10 ? '0' : '') + self.mon;
              case 'd': return (self.day  < 10 ? '0' : '') + self.day;
              case 'H': return (self.hour < 10 ? '0' : '') + self.hour;
              case 'M': return (self.min  < 10 ? '0' : '') + self.min;
              case 'S': return (self.sec  < 10 ? '0' : '') + self.sec;
            }
          });
        return date.toGMTString();
      }
    };
  },
  
  cookie: function (name, value, options) {
    if (arguments.length >= 2) {
      options = this.clone(options);
      if (!options.path)
        options.path = '/';
      
      if (value === null)
        options.days = -1;
      
      if (this.has(options.days)) {
        var exp = new Date;
        exp.setTime(exp.getTime() + (options.days * (1000 * 60 * 60 * 24)));
        options.expires = exp.toGMTString();
        delete options.days;
      }
      
      return d.cookie = name + '=' + value + this.map(options, function (key, value) {
        return '; ' + key + '=' + value;
      }).join('') + ';';
    }
    else {
      value = null;
      this.each(d.cookie.split(/;\s?/), function (cookie) {
        if (cookie.match(/^([^=]+)=(.*)$/) && RegExp.$1 == name) {
          value = RegExp.$2;
          return false;
        }
      });
      
      return value;
    }
  }
};
window.mm = self;
})();
