/**
 * gridstack.js 0.3.0
 * http://troolee.github.io/gridstack.js/
 * (c) 2014-2016 Pavel Reznikov, Dylan Weiss
 * gridstack.js may be freely distributed under the MIT license.
 * @preserve
 */
(function(factory) {
  if (typeof define === "function" && define.amd) {
    define(["jquery", "lodash"], factory);
  } else if (typeof exports !== "undefined") {
    try {
      jQuery = require("jquery");
    } catch (e) {}
    try {
      _ = require("lodash");
    } catch (e) {}
    factory(jQuery, _);
  } else {
    factory(jQuery, _);
  }
})(function($, _) {
  var scope = window;
  var obsolete = function(f, oldName, newName) {
    var wrapper = function() {
      console.warn(
        "gridstack.js: Function `" +
          oldName +
          "` is deprecated as of v0.2.5 and has been replaced " +
          "with `" +
          newName +
          "`. It will be **completely** removed in v1.0."
      );
      return f.apply(this, arguments);
    };
    wrapper.prototype = f.prototype;
    return wrapper;
  };
  var obsoleteOpts = function(oldName, newName) {
    console.warn(
      "gridstack.js: Option `" +
        oldName +
        "` is deprecated as of v0.2.5 and has been replaced with `" +
        newName +
        "`. It will be **completely** removed in v1.0."
    );
  };
  var Utils = {
    isIntercepted: function(a, b) {
      return !(
        a.x + a.width <= b.x ||
        b.x + b.width <= a.x ||
        a.y + a.height <= b.y ||
        b.y + b.height <= a.y
      );
    },
    sort: function(nodes, dir, width) {
      width =
        width ||
        _.chain(nodes)
          .map(function(node) {
            return node.x + node.width;
          })
          .max()
          .value();
      dir = dir != -1 ? 1 : -1;
      return _.sortBy(nodes, function(n) {
        return dir * (n.x + n.y * width);
      });
    },
    createStylesheet: function(id) {
      var style = document.createElement("style");
      style.setAttribute("type", "text/css");
      style.setAttribute("data-gs-style-id", id);
      if (style.styleSheet) {
        style.styleSheet.cssText = "";
      } else {
        style.appendChild(document.createTextNode(""));
      }
      document.getElementsByTagName("head")[0].appendChild(style);
      return style.sheet;
    },
    removeStylesheet: function(id) {
      $("STYLE[data-gs-style-id=" + id + "]").remove();
    },
    insertCSSRule: function(sheet, selector, rules, index) {
      if (typeof sheet.insertRule === "function") {
        sheet.insertRule(selector + "{" + rules + "}", index);
      } else if (typeof sheet.addRule === "function") {
        sheet.addRule(selector, rules, index);
      }
    },
    toBool: function(v) {
      if (typeof v == "boolean") {
        return v;
      }
      if (typeof v == "string") {
        v = v.toLowerCase();
        return !(v === "" || v == "no" || v == "false" || v == "0");
      }
      return Boolean(v);
    },
    _collisionNodeCheck: function(n) {
      return n != this.node && Utils.isIntercepted(n, this.nn);
    },
    _didCollide: function(bn) {
      return Utils.isIntercepted(
        {
          x: this.n.x,
          y: this.newY,
          width: this.n.width,
          height: this.n.height
        },
        bn
      );
    },
    _isAddNodeIntercepted: function(n) {
      return Utils.isIntercepted(
        {
          x: this.x,
          y: this.y,
          width: this.node.width,
          height: this.node.height
        },
        n
      );
    },
    parseHeight: function(val) {
      var height = val;
      var heightUnit = "px";
      if (height && _.isString(height)) {
        var match = height.match(
          /^(-[0-9]+\.[0-9]+|[0-9]*\.[0-9]+|-[0-9]+|[0-9]+)(px|em|rem|vh|vw)?$/
        );
        if (!match) {
          throw new Error("Invalid height");
        }
        heightUnit = match[2] || "px";
        height = parseFloat(match[1]);
      }
      return { height: height, unit: heightUnit };
    }
  };
  // jscs:disable requireCamelCaseOrUpperCaseIdentifiers
  Utils.is_intercepted = obsolete(
    Utils.isIntercepted,
    "is_intercepted",
    "isIntercepted"
  );
  Utils.create_stylesheet = obsolete(
    Utils.createStylesheet,
    "create_stylesheet",
    "createStylesheet"
  );
  Utils.remove_stylesheet = obsolete(
    Utils.removeStylesheet,
    "remove_stylesheet",
    "removeStylesheet"
  );
  Utils.insert_css_rule = obsolete(
    Utils.insertCSSRule,
    "insert_css_rule",
    "insertCSSRule"
  );
  // jscs:enable requireCamelCaseOrUpperCaseIdentifiers
  /**
   * @class GridStackDragDropPlugin
   * Base class for drag'n'drop plugin.
   */
  function GridStackDragDropPlugin(grid) {
    this.grid = grid;
  }
  GridStackDragDropPlugin.registeredPlugins = [];
  GridStackDragDropPlugin.registerPlugin = function(pluginClass) {
    GridStackDragDropPlugin.registeredPlugins.push(pluginClass);
  };
  GridStackDragDropPlugin.prototype.resizable = function(el, opts) {
    return this;
  };
  GridStackDragDropPlugin.prototype.draggable = function(el, opts) {
    return this;
  };
  GridStackDragDropPlugin.prototype.droppable = function(el, opts) {
    return this;
  };
  GridStackDragDropPlugin.prototype.isDroppable = function(el) {
    return false;
  };
  GridStackDragDropPlugin.prototype.on = function(el, eventName, callback) {
    return this;
  };
  var idSeq = 0;
  var GridStackEngine = function(width, onchange, floatMode, height, items) {
    this.width = width;
    this.float = floatMode || false;
    this.height = height || 0;
    this.nodes = items || [];
    this.onchange = onchange || function() {};
    this._updateCounter = 0;
    this._float = this.float;
    this._addedNodes = [];
    this._removedNodes = [];
  };
  GridStackEngine.prototype.batchUpdate = function() {
    this._updateCounter = 1;
    this.float = true;
  };
  GridStackEngine.prototype.commit = function() {
    if (this._updateCounter !== 0) {
      this._updateCounter = 0;
      this.float = this._float;
      this._packNodes();
      this._notify();
    }
  };
  // For Meteor support: https://github.com/troolee/gridstack.js/pull/272
  GridStackEngine.prototype.getNodeDataByDOMEl = function(el) {
    return _.find(this.nodes, function(n) {
      return el.get(0) === n.el.get(0);
    });
  };
  GridStackEngine.prototype._fixCollisions = function(node) {
    var self = this;
    this._sortNodes(-1);
    var nn = node;
    var hasLocked = Boolean(
      _.find(this.nodes, function(n) {
        return n.locked;
      })
    );
    if (!this.float && !hasLocked) {
      nn = { x: 0, y: node.y, width: this.width, height: node.height };
    }
    while (true) {
      var collisionNode = _.find(
        this.nodes,
        _.bind(Utils._collisionNodeCheck, { node: node, nn: nn })
      );
      if (typeof collisionNode == "undefined") {
        return;
      }
      this.moveNode(
        collisionNode,
        collisionNode.x,
        node.y + node.height,
        collisionNode.width,
        collisionNode.height,
        true
      );
    }
  };
  GridStackEngine.prototype.isAreaEmpty = function(x, y, width, height) {
    var nn = { x: x || 0, y: y || 0, width: width || 1, height: height || 1 };
    var collisionNode = _.find(
      this.nodes,
      _.bind(function(n) {
        return Utils.isIntercepted(n, nn);
      }, this)
    );
    return collisionNode === null || typeof collisionNode === "undefined";
  };
  GridStackEngine.prototype._sortNodes = function(dir) {
    this.nodes = Utils.sort(this.nodes, dir, this.width);
  };
  GridStackEngine.prototype._packNodes = function() {
    this._sortNodes();
    if (this.float) {
      _.each(
        this.nodes,
        _.bind(function(n, i) {
          if (
            n._updating ||
            typeof n._origY == "undefined" ||
            n.y == n._origY
          ) {
            return;
          }
          var newY = n.y;
          while (newY >= n._origY) {
            var collisionNode = _.chain(this.nodes)
              .find(_.bind(Utils._didCollide, { n: n, newY: newY }))
              .value();
            if (!collisionNode) {
              n._dirty = true;
              n.y = newY;
            }
            --newY;
          }
        }, this)
      );
    } else {
      _.each(
        this.nodes,
        _.bind(function(n, i) {
          if (n.locked) {
            return;
          }
          while (n.y > 0) {
            var newY = n.y - 1;
            var canBeMoved = i === 0;
            if (i > 0) {
              var collisionNode = _.chain(this.nodes)
                .take(i)
                .find(_.bind(Utils._didCollide, { n: n, newY: newY }))
                .value();
              canBeMoved = typeof collisionNode == "undefined";
            }
            if (!canBeMoved) {
              break;
            }
            n._dirty = n.y != newY;
            n.y = newY;
          }
        }, this)
      );
    }
  };
  GridStackEngine.prototype._prepareNode = function(node, resizing) {
    node = _.defaults(node || {}, { width: 1, height: 1, x: 0, y: 0 });
    node.x = parseInt("" + node.x);
    node.y = parseInt("" + node.y);
    node.width = parseInt("" + node.width);
    node.height = parseInt("" + node.height);
    node.autoPosition = node.autoPosition || false;
    node.noResize = node.noResize || false;
    node.noMove = node.noMove || false;
    if (node.width > this.width) {
      node.width = this.width;
    } else if (node.width < 1) {
      node.width = 1;
    }
    if (node.height < 1) {
      node.height = 1;
    }
    if (node.x < 0) {
      node.x = 0;
    }
    if (node.x + node.width > this.width) {
      if (resizing) {
        node.width = this.width - node.x;
      } else {
        node.x = this.width - node.width;
      }
    }
    if (node.y < 0) {
      node.y = 0;
    }
    return node;
  };
  GridStackEngine.prototype._notify = function() {
    var args = Array.prototype.slice.call(arguments, 0);
    args[0] = typeof args[0] === "undefined" ? [] : [args[0]];
    args[1] = typeof args[1] === "undefined" ? true : args[1];
    if (this._updateCounter) {
      return;
    }
    var deletedNodes = args[0].concat(this.getDirtyNodes());
    this.onchange(deletedNodes, args[1]);
  };
  GridStackEngine.prototype.cleanNodes = function() {
    if (this._updateCounter) {
      return;
    }
    _.each(this.nodes, function(n) {
      n._dirty = false;
    });
  };
  GridStackEngine.prototype.getDirtyNodes = function() {
    return _.filter(this.nodes, function(n) {
      return n._dirty;
    });
  };
  GridStackEngine.prototype.addNode = function(node, triggerAddEvent) {
    node = this._prepareNode(node);
    if (typeof node.maxWidth != "undefined") {
      node.width = Math.min(node.width, node.maxWidth);
    }
    if (typeof node.maxHeight != "undefined") {
      node.height = Math.min(node.height, node.maxHeight);
    }
    if (typeof node.minWidth != "undefined") {
      node.width = Math.max(node.width, node.minWidth);
    }
    if (typeof node.minHeight != "undefined") {
      node.height = Math.max(node.height, node.minHeight);
    }
    node._id = ++idSeq;
    node._dirty = true;
    if (node.autoPosition) {
      this._sortNodes();
      for (var i = 0; ; ++i) {
        var x = i % this.width;
        var y = Math.floor(i / this.width);
        if (x + node.width > this.width) {
          continue;
        }
        if (
          !_.find(
            this.nodes,
            _.bind(Utils._isAddNodeIntercepted, { x: x, y: y, node: node })
          )
        ) {
          node.x = x;
          node.y = y;
          break;
        }
      }
    }
    this.nodes.push(node);
    if (typeof triggerAddEvent != "undefined" && triggerAddEvent) {
      this._addedNodes.push(_.clone(node));
    }
    this._fixCollisions(node);
    this._packNodes();
    this._notify();
    return node;
  };
  GridStackEngine.prototype.removeNode = function(node, detachNode) {
    detachNode = typeof detachNode === "undefined" ? true : detachNode;
    this._removedNodes.push(_.clone(node));
    node._id = null;
    this.nodes = _.without(this.nodes, node);
    this._packNodes();
    this._notify(node, detachNode);
  };
  GridStackEngine.prototype.canMoveNode = function(node, x, y, width, height) {
    if (!this.isNodeChangedPosition(node, x, y, width, height)) {
      return false;
    }
    var hasLocked = Boolean(
      _.find(this.nodes, function(n) {
        return n.locked;
      })
    );
    if (!this.height && !hasLocked) {
      return true;
    }
    var clonedNode;
    var clone = new GridStackEngine(
      this.width,
      null,
      this.float,
      0,
      _.map(this.nodes, function(n) {
        if (n == node) {
          clonedNode = $.extend({}, n);
          return clonedNode;
        }
        return $.extend({}, n);
      })
    );
    if (typeof clonedNode === "undefined") {
      return true;
    }
    clone.moveNode(clonedNode, x, y, width, height);
    var res = true;
    if (hasLocked) {
      res &= !Boolean(
        _.find(clone.nodes, function(n) {
          return n != clonedNode && Boolean(n.locked) && Boolean(n._dirty);
        })
      );
    }
    if (this.height) {
      res &= clone.getGridHeight() <= this.height;
    }
    return res;
  };
  GridStackEngine.prototype.canBePlacedWithRespectToHeight = function(node) {
    if (!this.height) {
      return true;
    }
    var clone = new GridStackEngine(
      this.width,
      null,
      this.float,
      0,
      _.map(this.nodes, function(n) {
        return $.extend({}, n);
      })
    );
    clone.addNode(node);
    return clone.getGridHeight() <= this.height;
  };
  GridStackEngine.prototype.isNodeChangedPosition = function(
    node,
    x,
    y,
    width,
    height
  ) {
    if (typeof x != "number") {
      x = node.x;
    }
    if (typeof y != "number") {
      y = node.y;
    }
    if (typeof width != "number") {
      width = node.width;
    }
    if (typeof height != "number") {
      height = node.height;
    }
    if (typeof node.maxWidth != "undefined") {
      width = Math.min(width, node.maxWidth);
    }
    if (typeof node.maxHeight != "undefined") {
      height = Math.min(height, node.maxHeight);
    }
    if (typeof node.minWidth != "undefined") {
      width = Math.max(width, node.minWidth);
    }
    if (typeof node.minHeight != "undefined") {
      height = Math.max(height, node.minHeight);
    }
    if (
      node.x == x &&
      node.y == y &&
      node.width == width &&
      node.height == height
    ) {
      return false;
    }
    return true;
  };
  GridStackEngine.prototype.moveNode = function(
    node,
    x,
    y,
    width,
    height,
    noPack
  ) {
    if (!this.isNodeChangedPosition(node, x, y, width, height)) {
      return node;
    }
    if (typeof x != "number") {
      x = node.x;
    }
    if (typeof y != "number") {
      y = node.y;
    }
    if (typeof width != "number") {
      width = node.width;
    }
    if (typeof height != "number") {
      height = node.height;
    }
    if (typeof node.maxWidth != "undefined") {
      width = Math.min(width, node.maxWidth);
    }
    if (typeof node.maxHeight != "undefined") {
      height = Math.min(height, node.maxHeight);
    }
    if (typeof node.minWidth != "undefined") {
      width = Math.max(width, node.minWidth);
    }
    if (typeof node.minHeight != "undefined") {
      height = Math.max(height, node.minHeight);
    }
    if (
      node.x == x &&
      node.y == y &&
      node.width == width &&
      node.height == height
    ) {
      return node;
    }
    var resizing = node.width != width;
    node._dirty = true;
    node.x = x;
    node.y = y;
    node.width = width;
    node.height = height;
    node.lastTriedX = x;
    node.lastTriedY = y;
    node.lastTriedWidth = width;
    node.lastTriedHeight = height;
    node = this._prepareNode(node, resizing);
    this._fixCollisions(node);
    if (!noPack) {
      this._packNodes();
      this._notify();
    }
    return node;
  };
  GridStackEngine.prototype.getGridHeight = function() {
    return _.reduce(
      this.nodes,
      function(memo, n) {
        return Math.max(memo, n.y + n.height);
      },
      0
    );
  };
  GridStackEngine.prototype.beginUpdate = function(node) {
    _.each(this.nodes, function(n) {
      n._origY = n.y;
    });
    node._updating = true;
  };
  GridStackEngine.prototype.endUpdate = function() {
    _.each(this.nodes, function(n) {
      n._origY = n.y;
    });
    var n = _.find(this.nodes, function(n) {
      return n._updating;
    });
    if (n) {
      n._updating = false;
    }
  };
  var GridStack = function(el, opts) {
    var self = this;
    var oneColumnMode, isAutoCellHeight;
    opts = opts || {};
    this.container = $(el);
    // jscs:disable requireCamelCaseOrUpperCaseIdentifiers
    if (typeof opts.handle_class !== "undefined") {
      opts.handleClass = opts.handle_class;
      obsoleteOpts("handle_class", "handleClass");
    }
    if (typeof opts.item_class !== "undefined") {
      opts.itemClass = opts.item_class;
      obsoleteOpts("item_class", "itemClass");
    }
    if (typeof opts.placeholder_class !== "undefined") {
      opts.placeholderClass = opts.placeholder_class;
      obsoleteOpts("placeholder_class", "placeholderClass");
    }
    if (typeof opts.placeholder_text !== "undefined") {
      opts.placeholderText = opts.placeholder_text;
      obsoleteOpts("placeholder_text", "placeholderText");
    }
    if (typeof opts.cell_height !== "undefined") {
      opts.cellHeight = opts.cell_height;
      obsoleteOpts("cell_height", "cellHeight");
    }
    if (typeof opts.vertical_margin !== "undefined") {
      opts.verticalMargin = opts.vertical_margin;
      obsoleteOpts("vertical_margin", "verticalMargin");
    }
    if (typeof opts.min_width !== "undefined") {
      opts.minWidth = opts.min_width;
      obsoleteOpts("min_width", "minWidth");
    }
    if (typeof opts.static_grid !== "undefined") {
      opts.staticGrid = opts.static_grid;
      obsoleteOpts("static_grid", "staticGrid");
    }
    if (typeof opts.is_nested !== "undefined") {
      opts.isNested = opts.is_nested;
      obsoleteOpts("is_nested", "isNested");
    }
    if (typeof opts.always_show_resize_handle !== "undefined") {
      opts.alwaysShowResizeHandle = opts.always_show_resize_handle;
      obsoleteOpts("always_show_resize_handle", "alwaysShowResizeHandle");
    }
    // jscs:enable requireCamelCaseOrUpperCaseIdentifiers
    opts.itemClass = opts.itemClass || "grid-stack-item";
    var isNested = this.container.closest("." + opts.itemClass).length > 0;
    this.opts = _.defaults(opts || {}, {
      width: parseInt(this.container.attr("data-gs-width")) || 12,
      height: parseInt(this.container.attr("data-gs-height")) || 0,
      itemClass: "grid-stack-item",
      placeholderClass: "grid-stack-placeholder",
      placeholderText: "",
      handle: ".grid-stack-item-content",
      handleClass: null,
      cellHeight: 60,
      verticalMargin: 20,
      auto: true,
      minWidth: 768,
      float: false,
      staticGrid: false,
      _class: "grid-stack-instance-" + (Math.random() * 10000).toFixed(0),
      animate: Boolean(this.container.attr("data-gs-animate")) || false,
      alwaysShowResizeHandle: opts.alwaysShowResizeHandle || false,
      resizable: _.defaults(opts.resizable || {}, {
        autoHide: !(opts.alwaysShowResizeHandle || false),
        handles: "se"
      }),
      draggable: _.defaults(opts.draggable || {}, {
        handle:
          (opts.handleClass
            ? "." + opts.handleClass
            : opts.handle
            ? opts.handle
            : "") || ".grid-stack-item-content",
        scroll: false,
        appendTo: "body"
      }),
      disableDrag: opts.disableDrag || false,
      disableResize: opts.disableResize || false,
      rtl: "auto",
      removable: false,
      removeTimeout: 2000,
      verticalMarginUnit: "px",
      cellHeightUnit: "px",
      disableOneColumnMode: opts.disableOneColumnMode || false,
      oneColumnModeClass:
        opts.oneColumnModeClass || "grid-stack-one-column-mode",
      ddPlugin: null
    });
    if (this.opts.ddPlugin === false) {
      this.opts.ddPlugin = GridStackDragDropPlugin;
    } else if (this.opts.ddPlugin === null) {
      this.opts.ddPlugin =
        _.first(GridStackDragDropPlugin.registeredPlugins) ||
        GridStackDragDropPlugin;
    }
    this.dd = new this.opts.ddPlugin(this);
    if (this.opts.rtl === "auto") {
      this.opts.rtl = this.container.css("direction") === "rtl";
    }
    if (this.opts.rtl) {
      this.container.addClass("grid-stack-rtl");
    }
    this.opts.isNested = isNested;
    isAutoCellHeight = this.opts.cellHeight === "auto";
    if (isAutoCellHeight) {
      self.cellHeight(self.cellWidth(), true);
    } else {
      this.cellHeight(this.opts.cellHeight, true);
    }
    this.verticalMargin(this.opts.verticalMargin, true);
    this.container.addClass(this.opts._class);
    this._setStaticClass();
    if (isNested) {
      this.container.addClass("grid-stack-nested");
    }
    this._initStyles();
    this.grid = new GridStackEngine(
      this.opts.width,
      function(nodes, detachNode) {
        detachNode = typeof detachNode === "undefined" ? true : detachNode;
        var maxHeight = 0;
        _.each(nodes, function(n) {
          if (detachNode && n._id === null) {
            if (n.el) {
              n.el.remove();
            }
          } else {
            n.el
              .attr("data-gs-x", n.x)
              .attr("data-gs-y", n.y)
              .attr("data-gs-width", n.width)
              .attr("data-gs-height", n.height);
            maxHeight = Math.max(maxHeight, n.y + n.height);
          }
        });
        self._updateStyles(maxHeight + 10);
      },
      this.opts.float,
      this.opts.height
    );
    if (this.opts.auto) {
      var elements = [];
      var _this = this;
      this.container
        .children(
          "." +
            this.opts.itemClass +
            ":not(." +
            this.opts.placeholderClass +
            ")"
        )
        .each(function(index, el) {
          el = $(el);
          elements.push({
            el: el,
            i:
              parseInt(el.attr("data-gs-x")) +
              parseInt(el.attr("data-gs-y")) * _this.opts.width
          });
        });
      _.chain(elements)
        .sortBy(function(x) {
          return x.i;
        })
        .each(function(i) {
          self._prepareElement(i.el);
        })
        .value();
    }
    this.setAnimation(this.opts.animate);
    this.placeholder = $(
      '
' +
        '
' +
        this.opts.placeholderText +
        "