(function ($) {
  $.fn.memorize = function (settings) {

    if (settings) $.extend($.fn.memorize.defaults, settings);

    this.each(function () {
      $.fn.memorize.css($(this));
      $.fn.memorize.functions($(this));
    });

    return this;
  };

  $.fn.memorize.css = function (obj) {
    var csses = $.fn.memorize.defaults.css;
    var attrs = new Array();
    for (css in csses) {
      attrs[csses[css]] = obj.css(csses[css]);
    }
    obj.data('mem-css', attrs);
  };

  $.fn.memorize.functions = function (obj) {
    var funcs = $.fn.memorize.defaults.functions;
    var attrs = new Array();
    for (f in funcs) {
      attrs[funcs[f]] = obj[funcs[f]](); 
    }
    obj.data('mem-functions', attrs);
  };

  $.fn.revert = function(settings) {

    if (settings) $.extend($.fn.memorize.defaults, settings);

    this.each(function () {
      $.fn.memorize.revertCss($(this));
      $.fn.memorize.revertFunctions($(this));
    });

    return this;
  };

  $.fn.memorize.revertCss = function (obj) {
    obj.animate($.fn.memorize.get_dict(obj, 'mem-css', $.fn.memorize.defaults.css));
  };

  $.fn.memorize.revertFunctions = function (obj) {
    var funcs = $.fn.memorize.defaults.functions;
    for (f in funcs) {
      obj[funcs[f]](obj.data('mem-functions')[funcs[f]]);
    }
  };

  $.fn.memorize.get_dict = function (obj, data_name, type) {
    var dict = {};
    for (t in type) {
      dict[type[t]] = obj.data(data_name)[type[t]];
    }
    return dict;
  };

  $.fn.memorize.defaults = {
    css: ['height','width','top','left'],
    functions: ['html']
  };

})(jQuery);

