/******/ (function() { // webpackBootstrap
var CustomizeBuilder_V1;
(function ($) {
  var $document = $(document);
  var wpcustomize = wp.customize || null;
  var is_rtl = Customify_Layout_Builder.is_rtl;
  CustomizeBuilder_V1 = function (options, id) {
    var Builder = {
      id: id,
      controlId: "",
      cols: 12,
      cellHeight: 45,
      items: [],
      container: null,
      ready: false,
      devices: {
        desktop: "Desktop",
        mobile: "Mobile/Tablet"
      },
      activePanel: "desktop",
      panels: {},
      activeRow: "main",
      draggingItem: null,
      getTemplate: _.memoize(function () {
        var control = this;
        var compiled,
          /*
           * Underscore's default ERB-style templates are incompatible with PHP
           * when asp_tags is enabled, so WordPress uses Mustache-inspired templating syntax.
           *
           * @see trac ticket #22344.
           */
          options = {
            evaluate: /<#([\s\S]+?)#>/g,
            interpolate: /\{\{\{([\s\S]+?)\}\}\}/g,
            escape: /\{\{([^\}]+?)\}\}(?!\})/g,
            variable: "data"
          };
        return function (data, id, data_variable_name) {
          if (_.isUndefined(id)) {
            id = "tmpl-customize-control-" + control.type;
          }
          if (!_.isUndefined(data_variable_name) && _.isString(data_variable_name)) {
            options.variable = data_variable_name;
          } else {
            options.variable = "data";
          }
          compiled = _.template($("#" + id).html(), null, options);
          return compiled(data);
        };
      }),
      drag_drop: function () {
        var that = this;
        $(".customify--device-panel", that.container).each(function () {
          var panel = $(this);
          var device = panel.data("device");
          var sortable_ids = [];
          that.panels[device] = {};
          $(".customify--cb-items", panel).each(function (index) {
            var data_name = $(this).attr("data-id") || "";
            var id;
            if (!data_name) {
              id = "_sid_" + device + index;
            } else {
              id = "_sid_" + device + "-" + data_name;
            }
            $(this).attr("id", id);
            sortable_ids[index] = "#" + id;
          });
          $(".grid-stack", panel).each(function () {
            var _id = $(this).attr("data-id") || "";
            that.panels[device][_id] = $(this);
            $(this).droppable({
              out: function (event, ui) {},
              over: function (event, ui) {
                //var $wrapper = $( this );
                /**
                 * @see http://api.jqueryui.com/droppable/#event-over
                 */
              },
              drop: function (event, ui) {
                var $wrapper = $(this);
                that.gridster($wrapper, ui, event);
                that.save();
              }
            });
          });
          var sidebar = $("#_sid_mobile-sidebar", panel);
          var sidebar_id = sidebar.attr("id") || false;
          $(".customify-available-items .grid-stack-item", panel).draggable({
            revert: "invalid",
            connectToSortable: sidebar_id ? "#" + sidebar_id : false,
            start: function (event, ui) {
              $("body").addClass("builder-item-moving");
              $(".customify--cb-items", panel).css("z-index", "");
              ui.helper.parent().css("z-index", 9999);
            },
            stop: function (event, ui) {
              $("body").removeClass("builder-item-moving");
              $(".customify--cb-items", panel).css("z-index", "");
              ui.helper.parent().css("z-index", "");
            }
          });
          if (sidebar.length > 0) {
            sidebar.sortable({
              revert: true,
              change: function (event, ui) {
                that.save();
              },
              receive: function (event, ui) {
                $(this).find(".grid-stack-item").removeAttr("style").attr("data-gs-width", 1);
                that.save();
              }
            });
            that.panels[device]["sidebar"] = sidebar;
          }
          $(".customify-available-items .grid-stack-item", panel).resizable({
            handles: "w, e",
            stop: function (event, ui) {
              that.setGridWidth(ui.element.parent(), ui);
              that.save();
            }
          });
        });
      },
      sortGrid: function ($wrapper) {
        $(".grid-stack-item", $wrapper).each(function () {
          var el = $(this);
          var x = el.attr("data-gs-x") || 0;
          x = parseInt(x);
          var next = el.next();
          if (next.length > 0) {
            var nx = next.attr("data-gs-x") || 0;
            nx = parseInt(nx);
            if (x > nx) {
              el.insertAfter(next);
            }
          }
        });
      },
      getX: function ($item) {
        var x = $item.attr("data-gs-x") || 0;
        return parseInt(x);
      },
      getW: function ($item, df) {
        if (_.isUndefined(df)) {
          df = false;
        }
        var w;
        if (df) {
          w = $item.attr("data-df-width") || 1;
        } else {
          w = $item.attr("data-gs-width") || 1;
        }
        return parseInt(w);
      },
      gridGetItemInfo: function ($item, flag, $wrapper) {
        var that = this;
        var x = that.getX($item);
        var w = that.getW($item);
        var slot_before = 0;
        var slot_after = 0;
        var i;
        var br = false;
        // Get empty slots before
        i = x - 1;
        while (i >= 0 && !br) {
          if (flag[i] === 0) {
            slot_before++;
          } else {
            br = true;
          }
          i--;
        }

        // Get empty slots after
        br = false;
        i = x + w;
        while (i < that.cols && !br) {
          if (flag[i] === 0) {
            slot_after++;
          } else {
            br = true;
          }
          i++;
        }
        return {
          flag: flag,
          x: x,
          w: w,
          item: $item,
          before: slot_before,
          // empty before
          after: slot_after,
          // empty after
          id: $item.attr("data-id") || "",
          wrapper: $wrapper
        };
      },
      updateItemsPositions: function (flag) {
        var maxCol = this.cols;
        for (var i = 0; i <= maxCol; i++) {
          if (typeof flag[i] === "object" || typeof flag[i] === "function") {
            flag[i].attr("data-gs-x", i);
          }
        }
      },
      gridster: function ($wrapper, ui, event) {
        var flag = [],
          backupFlag = [],
          that = this;
        var maxCol = this.cols;
        var addItemToFlag = function (node) {
          var x = node.x,
            w = node.w;
          var el = node.el;
          for (var i = x; i < x + w; i++) {
            if (i === x) {
              flag[i] = el; // mean start item item
            } else {
              flag[i] = 1;
            }
          }
        };
        var removeNode = function (node) {
          var x = node.x,
            w = node.w;
          var el = node.el;
          for (var i = x; i < x + w; i++) {
            flag[i] = 0;
          }
        };
        var getEmptySlots = function () {
          var emptySlots = 0;
          for (var i = 0; i < maxCol; i++) {
            if (flag[i] === 0) {
              emptySlots++;
            }
          }
          return emptySlots;
        };
        var getRightEmptySlotFromX = function (x, stopWhenNotEmpty) {
          var emptySlots = 0;
          for (var i = x; i < maxCol; i++) {
            if (flag[i] === 0) {
              emptySlots++;
            } else {
              if (stopWhenNotEmpty) {
                return emptySlots;
              }
            }
          }
          return emptySlots;
        };
        var getLeftEmptySlotFromX = function (x, stopWhenNotEmpty) {
          var emptySlots = 0;
          if (typeof stopWhenNotEmpty === "undefined") {
            stopWhenNotEmpty = false;
          }
          for (var i = x; i >= 0; i--) {
            if (flag[i] === 0) {
              emptySlots++;
            } else {
              if (stopWhenNotEmpty) {
                return emptySlots;
              }
            }
          }
          return emptySlots;
        };
        var isEmptyX = function (x) {
          if (flag[x] === 0) {
            return true;
          }
          return false;
        };
        var checkEnoughSpaceFromX = function (x, w) {
          var check = true;
          var i = x;
          var j;
          while (i < x + w && check) {
            if (flag[i] !== 0) {
              return false;
            }
            i++;
          }
          return check;
        };
        var getPrevBlock = function (x) {
          if (x < 0) {
            return {
              x: -1,
              w: 1
            };
          }
          var i,
            _x = -1,
            _xw,
            found;
          if (flag[x] <= 1) {
            i = x;
            found = false;
            while (i >= 0 && !found) {
              if (flag[i] !== 1 && flag[i] !== 0) {
                _x = i;
                found = true;
              }
              i--;
            }
          } else {
            _x = x;
          }
          // tìm kiếm độ rộng của chuỗi này
          i = _x + 1;
          _xw = _x; // chiều rộng nhỏ nhất là môt

          while (flag[i] === 1) {
            _xw++;
            i++;
          }
          return {
            x: _x,
            w: _xw + 1 - _x
          };
        };
        var getNextBlock = function (x) {
          var i,
            _x = -1,
            _xw,
            found;
          if (flag[x] < maxCol) {
            i = x;
            found = false;
            while (i < maxCol && !found) {
              if (flag[i] !== 1 && flag[i] !== 0) {
                _x = i;
                found = true;
              }
              i++;
            }
          } else {
            _x = x;
          }
          // Calculate the width of this item
          i = _x + 1;
          _xw = _x; // the min width is 1

          while (flag[i] === 1) {
            _xw++;
            i++;
          }
          return {
            x: _x,
            w: _xw + 1 - _x
          };
        };

        /**
         *  Move all Items form x to left
         * @param x
         * @param number position left need to move
         * @returns {*}
         */
        var moveAllItemsFromXToLeft = function (x, number) {
          var backupFlag = flag.slice();
          var maxNumber = getLeftEmptySlotFromX(x);
          if (maxNumber === 0) {
            return number;
          }
          var prev = getPrevBlock(x);
          var newX = prev.x >= 0 ? prev.x + prev.w - 1 : x;
          var nMove = number;
          if (number > maxNumber) {
            nMove = maxNumber;
          } else {
            nMove = number;
          }

          // Find empty positions from x to left;
          // xE is new empty position from x
          var xE = 0,
            c = 0,
            i = newX;
          while (c <= nMove && i >= 0) {
            if (flag[i] === 0) {
              c++;
              xE = i;
            }
            i--;
          }

          // Move item from x to xE and we need empty flag from x to xE
          var flagNoEmpty = [],
            j = 0;
          for (i = xE; i <= newX; i++) {
            flag[i] = 0;
            if (backupFlag[i] !== 0) {
              flagNoEmpty[j] = backupFlag[i];
              j++;
            }
          }
          j = 0;
          for (i = xE; i <= newX; i++) {
            if (typeof flagNoEmpty[j] !== "undefined") {
              flag[i] = flagNoEmpty[j];
            } else {
              flag[i] = 0;
            }
            j++;
          }

          // Return the number positions need to move
          var left = number - nMove;
          return left;
        };
        var moveAllItemsFromXToRight = function (x, number) {
          var backupFlag = flag.slice();
          var maxNumber = getRightEmptySlotFromX(x);
          if (maxNumber === 0) {
            return number;
          }
          var prev = getPrevBlock(x);
          var newX = prev.x >= 0 ? prev.x : x;
          var nMove = number;
          if (number <= maxNumber) {
            nMove = number;
          } else {
            nMove = maxNumber;
          }

          // Find empty positions from x to right, stop when see any item while finding.
          var xE = x,
            c = 0,
            i = newX;
          while (c < nMove && i < maxCol) {
            if (flag[i] === 0) {
              c++;
              xE = i;
            }
            i++;
          }

          // The new position is x, and need empty flag from x to xE
          var flagNoEmpty = [],
            j = 0;
          for (i = newX; i <= xE; i++) {
            flag[i] = 0;
            if (backupFlag[i] !== 0) {
              flagNoEmpty[j] = backupFlag[i];
              j++;
            }
          }
          j = flagNoEmpty.length - 1;
          for (i = xE; i >= newX; i--) {
            if (typeof flagNoEmpty[j] !== "undefined") {
              flag[i] = flagNoEmpty[j];
            } else {
              flag[i] = 0;
            }
            j--;
          }

          // Return the number positions need to move
          var left = number - nMove;
          return left;
        };
        var updateItemsPositions = function () {
          that.updateItemsPositions(flag);
        };

        /**
         * Insert to Flag an item with the width is x and position is x
         *
         * @param node object Item node
         * @param swap boolean swap items or not
         * @returns {boolean}
         */
        var insertToFlag = function (node, swap) {
          var x = node.x,
            w = node.w;

          // get Empty slots
          var emptySlots = getEmptySlots();

          // Not enough empty slots, fallback.
          if (emptySlots <= 0) {
            return false;
          }
          if (_.isUndefined(swap)) {
            swap = false;
          }
          var _x;
          var _re;
          var _le;
          var _w;

          // Check nếu từ vị trí hiện tại đủ chỗ trống rồi thì ko cần dịch chuyển nữa.
          if (!swap) {
            if (isEmptyX(x)) {
              // Nếu đã đủ chỗ trống ko cần resize
              _w = w;
              if (checkEnoughSpaceFromX(x, _w)) {
                addItemToFlag(node);
                node.el.attr("data-gs-x", x);
                node.el.attr("data-gs-width", _w);
                return true;
              }
              _re = getRightEmptySlotFromX(x, true);
              _le = getLeftEmptySlotFromX(x - 1, true);

              // Kiểm tra xem tổng số chỗ trống có lớn hơn chiều rộng hiện tại không
              // Và số trống còn thiếu về bên trái phải nhỏ hơn số chỗ trống bên trái
              if (_re + _le >= w && w - _re <= _le) {
                _x = x - (w - _re);
              } else {
                _x = x - _le;
              }
              if (_x < 0) {
                _x = 0;
              }
              while (_w >= 1) {
                if (checkEnoughSpaceFromX(_x, _w)) {
                  node.x = _x;
                  node.w = _w;
                  addItemToFlag(node);
                  node.el.attr("data-gs-x", _x);
                  node.el.attr("data-gs-width", _w);
                  return true;
                }
                _w--;
              }
            }

            // Check nếu vị trí hiện tại x  có giá trị là 1 thì thử lùi về sau xem có chỗ nào đủ chỗ trống ko ?
            if (flag[x] === 1) {
              var prev = getPrevBlock(x);
              if (prev.x >= 0) {
                if (x > prev.x + Math.floor(prev.w / 2) && x > prev.x) {
                  _x = prev.x + prev.w;
                  _re = getRightEmptySlotFromX(_x, true);
                  if (_re >= w) {
                    addItemToFlag({
                      el: node.el,
                      x: _x,
                      w: w
                    });
                    node.el.attr("data-gs-x", _x);
                    node.el.attr("data-gs-width", w);
                    return true;
                  }
                }
              }
            }
          }
          var remain = 0;

          // -------------------------
          var _move_to_swap = function (node, _x) {
            var _block_prev;
            var _block_next;
            var _empty_slots = 0;
            var found = false;
            var i, el, er;
            if (isEmptyX(_x)) {
              // if insert at empty x
              _block_prev = getPrevBlock(_x);
              _block_next = getNextBlock(_x);
              if (_block_prev.x > -1) {
                // if drop item at position that have item before
                _empty_slots = getRightEmptySlotFromX(_block_prev.x); // find number empty slots from x top when have item
                if (_empty_slots >= node.w) {
                  // If enough slot for this item
                  if (checkEnoughSpaceFromX(_x, node.w)) {
                    x = _x;
                    found = true;
                  } else if (node.ox > _x) {
                    // move item from left to right
                    i = _block_prev.x + _block_prev.w;
                    el = getLeftEmptySlotFromX(i);
                    if (el <= node.w) {
                      el = node.w - el;
                    } else {
                      el = node.w;
                    }
                    moveAllItemsFromXToRight(i + 1, el);
                    _empty_slots = getRightEmptySlotFromX(i);
                    found = false;
                    while (i > _block_prev.x + _block_prev.w && !found) {
                      if (checkEnoughSpaceFromX(i, node.w)) {
                        x = i;
                        found = true;
                      }
                      i--;
                    }
                  }
                }
                if (!found && node.ox < _x) {
                  // move item from left to right
                  // try move item to the left
                  i = _block_prev.x + _block_prev.w - 1;
                  el = getLeftEmptySlotFromX(_block_prev.x);
                  if (el > node.w) {
                    el = node.w;
                  }
                  el -= 2;
                  moveAllItemsFromXToLeft(_block_prev.x, el);
                  _empty_slots = getRightEmptySlotFromX(i);
                  i -= _empty_slots;
                  _block_next = getNextBlock(_x);
                  var max = _block_prev.x + _block_prev.w;
                  if (_block_next.x > -1) {
                    max = _block_next.x;
                  }
                  while (i < max && !found) {
                    if (checkEnoughSpaceFromX(i, node.w)) {
                      x = i;
                      found = true;
                    }
                    i++;
                  }
                }
                if (!found) {
                  // Try to resize node width;
                  x = _block_prev.x + _block_prev.w;
                  node.w = _empty_slots;
                  node.x = x;
                }
              } else if (_block_next.x > -1) {
                // try to get right item form x
                _block_next = getNextBlock(_x);
                _empty_slots = getRightEmptySlotFromX(_x, false);
                var n_move = _empty_slots >= node.w ? node.w : _empty_slots;
                moveAllItemsFromXToRight(_x, n_move);
                i = _block_next.x;
                while (i >= 0 && !found) {
                  if (checkEnoughSpaceFromX(i, node.w)) {
                    x = i;
                    node.x = x;
                    found = true;
                  }
                  i--;
                }
                if (!found) {
                  // Try to resize node width;
                  x = _x;
                  node.w = _empty_slots;
                  node.x = x;
                }
              } else {
                // the row is empty
                // Do somthing
              }
            } else {
              // if x is not empty
              // insert before item, that drop in
              _block_prev = getPrevBlock(_x);
              if (node.ox < _block_prev.x) {
                // drop from left to right
                moveAllItemsFromXToLeft(_x, node.w);
                if (isEmptyX(_x)) {
                  x = _x;
                } else {
                  while (!isEmptyX(_x) && _x <= that.cols - 1) {
                    _x++;
                  }
                  x = _x;
                }
              } else {
                moveAllItemsFromXToRight(_x, node.w);
                if (isEmptyX(_x)) {
                  x = _x;
                } else {
                  while (!isEmptyX(_x) && _x >= 0) {
                    _x--;
                  }
                  x = _x;
                }
              }
            }
            if (x > that.cols) {
              x = that.cols - 1;
            }
            node.x = x;
          };
          _move_to_swap(node, _.clone(x));

          // console.log( '--------------------------------------------------------' );
          // -------------------------
          var newX = x;
          var i;
          var found = false;
          var le = 0;

          //console.log( 'in_the_end_x', x );
          //console.log( 'in_the_end_w', w );
          if (x + w > that.cols - 1) {
            le = getLeftEmptySlotFromX(x, true);
            if (le > 0) {}
          }
          updateItemsPositions();
          //console.log( 'Flag update', flag );
          le = 0;
          while (w >= 1) {
            // Nếu số chỗ trống lớn hơn hoặc  = chiều rộng của item
            if (emptySlots >= w) {
              // Nếu tại vị trí hiện tại mà đủ chỗ trống
              if (checkEnoughSpaceFromX(x, w)) {
                node.w = w;
                addItemToFlag(node);
                node.el.attr("data-gs-x", x);
                node.el.attr("data-gs-width", w);
                return true;
              }
              found = false;
              le = getLeftEmptySlotFromX(x, true);
              // Nếu trỗ trông bên trái nhiều hơn bên phải
              newX = x - le;
              // tìm kiếm từ vị trí trống từ new sang bên phải xem có chỗ nào chèn dc ko ?
              i = newX;
              while (i < maxCol && !found) {
                if (checkEnoughSpaceFromX(i, w)) {
                  node.w = w;
                  addItemToFlag({
                    el: node.el,
                    x: i,
                    w: w
                  });
                  node.el.attr("data-gs-x", i);
                  node.el.attr("data-gs-width", w);
                  found = true;
                  return true;
                }
                i++;
              }
            }
            w--;
          }

          // Chèn vào bất kỳ đâu đủ chỗ
          w = node.w;
          found = false;
          while (w >= 1) {
            i = 0;
            while (i < maxCol && !found) {
              if (checkEnoughSpaceFromX(i, w)) {
                addItemToFlag({
                  el: node.el,
                  x: i,
                  w: w
                });
                node.el.attr("data-gs-x", i);
                node.el.attr("data-gs-width", w);
                found = true;
                return true;
              }
              i++;
            }
            w--;
          }
          return false;
        };

        /**
         * Dổi chỗ 2 item trong 1 hàng
         * @param x Vị trị bắt đầu của item dc thay đổi
         * @param newX Vị trí của item chuyển đến
         */
        var swap = function (node, newX) {
          var x = node.x;
          var w = node.w;
          removeNode(node);
          var block2 = getPrevBlock(newX);
          var block2_right = 0;
          if (block2.x > -1) {
            block2_right = block2.x + block2.w;
          }
          if (checkEnoughSpaceFromX(newX, w)) {
            addItemToFlag({
              el: node.el,
              x: newX,
              w: w
            });
            return true;
          } else if (block2_right > 0 && checkEnoughSpaceFromX(block2_right, w) && newX >= block2_right) {
            var block3 = getNextBlock(newX);
            if (block3.x > -1) {
              // Nếu phía sau nó có item
              // nếu item chèn vào mà đủ chỗ
              // nhưng từ trí từ vị trí thả chuột xuống ko đủ chỗ để chèn vào
              // lùi vị trí chèn vào cho đến khi nào đủ
              if (node.w + newX >= block3.x) {
                var _newX = _.clone(newX);
                while (_newX > block2_right) {
                  if (checkEnoughSpaceFromX(_newX, w)) {
                    addItemToFlag({
                      el: node.el,
                      x: _newX,
                      w: w
                    });
                    return true;
                  }
                  _newX--;
                }
              }
            }
            if (newX + w > that.cols) {
              // Nếu newX + w vượt quá số cols. thì thử lùi lại xem  có đủ chỗ ko ?
              var _x = that.cols - w;
              if (checkEnoughSpaceFromX(_x, w)) {
                addItemToFlag({
                  el: node.el,
                  x: _x,
                  w: w
                });
                return true;
              }
            }
            addItemToFlag({
              el: node.el,
              x: block2_right,
              w: w
            });
            return true;
          }
          node.x = newX;
          insertToFlag(node, true);
        };

        //-----------------------------------------------------------------------------------------------------------------------------
        var that = this;
        flag = that.getFlag($wrapper);
        backupFlag = flag.slice();
        var wOffset = $wrapper.offset();
        that.draggingItem = ui.draggable;
        var width = $wrapper.width();
        var colWidth = width / that.cols;
        var x = 0;
        var iOffset = ui.offset;
        var w, cw, itemWidth, in_this_row;
        cw = that.getW(ui.draggable, false);
        w = that.getW(ui.draggable, true);
        itemWidth = ui.draggable.width();
        var ox = that.getX(ui.draggable);
        if (is_rtl) {
          removeNode({
            el: ui.draggable,
            x: ox,
            w: w
          });
        }
        var xc = 0,
          xi = 0,
          found = false;
        if (!ui.draggable.parent().is($wrapper)) {
          in_this_row = false;
          if (w < cw) {
            w = cw;
          }
        } else {
          in_this_row = true;
          w = cw;
        }

        // Kiểm tra RTL
        if (!is_rtl) {
          // nếu ko phải RTL
          // Lấy vị trí thả xuống từ con trỏ chuột tính theo bên trái của trình duyệt và mép trái của row
          xc = Math.round((event.clientX - wOffset.left) / colWidth);

          // Lấy vị trí thả xuống từ mép trái của item
          xi = Math.round((iOffset.left - wOffset.left - 10) / colWidth);
          if (xi < 0) {
            xi = 0;
          }
        } else {
          // Nếu là RTL

          // Lấy vị trí thả xuống từ con trỏ chuột tính theo bên trái của trình duyệt và mép phải của row
          xc = Math.round((wOffset.left + width + 10 - event.clientX) / colWidth);

          // Lấy vị trí thả xuống từ mép phải của item theo bên phải của row
          xi = Math.round((wOffset.left + width - (iOffset.left + itemWidth + 10)) / colWidth);
          if (xi < 0) {
            xi = 0;
          }
        }
        if (xc > that.cols) {
          xc = that.cols;
        }
        x = xi;
        var _i;
        _i = xi;
        if (is_rtl) {
          if (!isEmptyX(_i)) {
            while (_i < that.cols && !found) {
              if (isEmptyX(_i)) {
                found = true;
              } else {
                _i++;
              }
            }
            if (x > xc) {
              // x = xc;
            }
          } else {
            x = xi;
            found = true;
          }
        } else {
          if (!isEmptyX(x)) {
            while (x <= xc && !found) {
              if (isEmptyX(x)) {
                found = true;
              } else {
                x++;
              }
            }
            if (x > xc) {
              x = xc;
            }
          } else {
            x = xi;
            found = true;
          }
        }
        if (!found) {
          if (in_this_row) {
            x = xi;
          } else {
            x = xc;
          }
        }
        if (x < 0) {
          x = 0;
        }
        if (x + w >= that.cols) {
          found = true;
          _i = x;
          while (_i + w > that.cols && found) {
            if (!isEmptyX(_i)) {
              _i++;
              found = false;
            } else {
              _i--;
            }
          }
          x = _i;
        }
        found = null;
        var node = {
          el: ui.draggable,
          x: x,
          w: w,
          ox: ox,
          ow: cw
        };
        if (node.x <= 0) {
          node.x = 0;
        }
        var did = false;
        if (in_this_row) {
          node.x = parseInt(ui.draggable.attr("data-gs-x") || 0);
          node.w = parseInt(ui.draggable.attr("data-gs-width") || 1);
          swap(node, x);
          did = true;
        } else {
          did = insertToFlag(node);
        }

        // console.log( 'Drop on X: ' + x + ', width: '+ w );
        // console.log( 'Drop Flag: ', flag );

        if (!did) {
          ui.draggable.removeAttr("style");
          flag = backupFlag; // rollback;
        } else {
          // Add drop item from somewhere to current row
          ui.draggable.removeClass("item-from-list");
          $wrapper.append(ui.draggable);
          ui.draggable.removeAttr("style");
          //ui.draggable.attr( 'data-gs-x', x );
          //ui.draggable.attr( 'data-gs-y', y );
          that.draggingItem = null;
        }
        updateItemsPositions();
        that.updateAllGrids();

        //-----------------------------------------------------------------------------------------------------------------------------
      },
      updateAllGrids: function () {
        var that = this;
        _.each(that.panels[that.activePanel], function (row, row_id) {
          that.updateGridFlag(row);
        });
      },
      setGridWidth: function ($wrapper, ui) {
        var that = this;
        var $item = ui.element;
        var width = $wrapper.width();
        var itemWidth = ui.size.width;
        var originalElementWidth = ui.originalSize.width;
        var colWidth = Math.ceil(width / that.cols) - 1;
        var isShiftLeft, isShiftRight;
        if (!is_rtl) {
          isShiftLeft = ui.originalPosition.left > ui.position.left;
          isShiftRight = ui.originalPosition.left < ui.position.left;
        } else {
          isShiftLeft = ui.originalPosition.left > ui.position.left;
          isShiftRight = originalElementWidth !== itemWidth;
        }
        var ow = ui.originalElement.attr("data-gs-width") || 1;
        var ox = ui.originalElement.attr("data-gs-x") || 0;
        ow = parseInt(ow);
        ox = parseInt(ox);
        var addW;
        var newX;
        var newW;
        var flag = that.getFlag($wrapper);
        var itemInfo = that.gridGetItemInfo(ui.originalElement, flag, $wrapper);
        var diffLeft, diffRight;
        if (isShiftLeft) {
          if (!is_rtl) {
            // Ok
            newX = Math.floor((ui.position.left - 1) / colWidth);
            addW = ox - newX;
            if (addW > itemInfo.before) {
              addW = itemInfo.before;
            }
            newX = ox - addW;
            newW = ow + addW;
            $item.attr("data-gs-x", newX).removeAttr("style");
            $item.attr("data-gs-width", newW).removeAttr("style");
          } else {
            // RTL

            // Ok
            newX = Math.floor((ui.position.left - 1) / colWidth);
            newX = that.cols - newX;
            addW = newX - ox - ow;
            if (addW > itemInfo.after) {
              addW = itemInfo.after;
            }
            newW = ow + addW;
            $item.attr("data-gs-x", ox).removeAttr("style");
            $item.attr("data-gs-width", newW).removeAttr("style");
          }
          that.updateGridFlag($wrapper);
          return;
        } else if (isShiftRight) {
          if (!is_rtl) {
            // Ok
            newX = Math.round((ui.position.left - 1) / colWidth);
            addW = newX - ox;
            newW = ow - addW;
            if (newW <= 0) {
              newW = 1;
              addW = 0;
            }
            newX = ox + addW;
            $item.attr("data-gs-x", newX).removeAttr("style");
            $item.attr("data-gs-width", newW).removeAttr("style");
          } else {
            // RTL

            if (ui.originalPosition.left !== ui.position.left) {
              // Nếu resize ở mép trái của Item
              // Ok
              newX = Math.floor((ui.position.left - 1) / colWidth);
              newX = that.cols - newX;
              addW = ow + ox - newX;
              if (addW > ow) {
                addW = 0;
              }
              newX = ox;
              newW = ow - addW;
              if (newX <= 0) {
                newX = 0;
              }
            } else {
              // Nếu resize ở mép phải của Item
              // Ok
              newX = Math.ceil((ui.position.left + ui.size.width - 11) / colWidth);
              newX = that.cols - newX;
              addW = ox - newX;
              if (addW > itemInfo.before) {
                addW = itemInfo.before;
              }
              newX = ox - addW;
              newW = ow + addW;
            }
            $item.attr("data-gs-x", newX).removeAttr("style");
            $item.attr("data-gs-width", newW).removeAttr("style");
          }
          that.updateGridFlag($wrapper);
          return;
        }
        var w;
        var x = itemInfo.x;
        var x_c;
        if (itemWidth < ui.originalSize.width) {
          // Resize from right to left
          // Ok
          x_c = Math.round((ui.position.left + ui.size.width - 11) / colWidth);
          if (x_c <= x) {
            x_c = x + 1;
          }
          w = itemInfo.w - (x + itemInfo.w - x_c);
        } else {
          // Resize from left to right
          //Ok
          x_c = Math.ceil((ui.position.left + ui.size.width - 11) / colWidth);
          w = itemInfo.w + (x_c - (x + itemInfo.w));
          if (itemInfo.x + w > itemInfo.x + itemInfo.w + itemInfo.after) {
            w = itemInfo.w + itemInfo.after;
          }
        }
        if (w <= 0) {
          w = 1;
        }
        $item.attr("data-gs-width", w).removeAttr("style");
        that.updateGridFlag($wrapper);
      },
      getFlag: function ($row) {
        var that = this;
        var flag = $row.data("gridRowFlag") || [];
        var i;
        if (_.isEmpty(flag)) {
          for (i = 0; i < that.cols; i++) {
            flag[i] = 0;
          }
          $row.data("gridRowFlag", flag);
        }
        return flag;
      },
      updateGridFlag: function ($row) {
        var that = this;
        var rowFlag = [];
        var i;
        for (i = 0; i < that.cols; i++) {
          rowFlag[i] = 0;
        }
        var items;
        items = $(".grid-stack-item", $row);
        items.each(function (index) {
          $(this).removeAttr("style");
          var x = that.getX($(this));
          var w = that.getW($(this));
          for (i = x; i < x + w; i++) {
            if (i === x) {
              rowFlag[i] = $(this);
            } else {
              rowFlag[i] = 1;
            }
          }
        });
        $row.data("gridRowFlag", rowFlag);
        that.updateItemsPositions(rowFlag);
        that.sortGrid($row);
        return rowFlag;
      },
      addNewWidget: function ($item, row) {
        var that = this;
        var panel = that.container.find(".customify--device-panel.customify--panel-" + that.activePanel);
        var el = row;
        if (!_.isObject(el)) {
          el = panel.find(".customify--cb-items").first();
        }
        var elItem = $item;
        elItem.draggable({
          revert: "invalid",
          appendTo: panel,
          scroll: false,
          zIndex: 99999,
          handle: ".grid-stack-item-content",
          start: function (event, ui) {
            $("body").addClass("builder-item-moving");
            $(".customify--cb-items", panel).css("z-index", "");
            ui.helper.parent().css("z-index", 9999);
          },
          stop: function (event, ui) {
            $("body").removeClass("builder-item-moving");
            $(".customify--cb-items", panel).css("z-index", "");
            that.save();
          },
          drag: function (event, ui) {}
        }).resizable({
          handles: "w, e",
          start: function (event, ui) {
            // RTL
            ui.originalElement.css({
              right: "auto",
              left: ui.position.left
            });
          },
          stop: function (event, ui) {
            that.setGridWidth(ui.element.parent(), ui);
            that.save();
          }
        });
        el.append(elItem);
        that.updateGridFlag(el);
      },
      addPanel: function (device) {
        var that = this;
        var template = that.getTemplate();
        var template_id = "tmpl-customify--cb-panel";
        if ($("#" + template_id).length == 0) {
          return;
        }
        if (!_.isObject(options.rows)) {
          options.rows = {};
        }
        var html = template({
          device: device,
          id: options.id,
          rows: options.rows
        }, template_id);
        return '<div class="customify--device-panel customify-vertical-panel customify--panel-' + device + '" data-device="' + device + '">' + html + "</div>";
      },
      addDevicePanels: function () {
        var that = this;
        _.each(that.devices, function (device_name, device) {
          var panelHTML = that.addPanel(device);
          $(".customify--cb-devices-switcher", that.container).append('<a href="#" class="switch-to switch-to-' + device + '" data-device="' + device + '">' + device_name + "</a>");
          $(".customify--cb-body", that.container).append(panelHTML);
        });
        if ($("#customify-upsell-tmpl").length) {
          $($("#customify-upsell-tmpl").html()).insertAfter($(".customify--cb-devices-switcher", that.container));
        }
      },
      addItem: function (node) {
        var that = this;
        var template = that.getTemplate();
        var template_id = "tmpl-customify--cb-item";
        if ($("#" + template_id).length == 0) {
          return;
        }
        var html = template(node, template_id);
        return $(html);
      },
      addAvailableItems: function () {
        var that = this;
        _.each(that.devices, function (device_name, device) {
          var $itemWrapper = $('<div class="customify-available-items" data-device="' + device + '"></div>');
          $(".customify--panel-" + device, that.container).append($itemWrapper);
          _.each(that.items, function (node) {
            var _d = true;
            if (!_.isUndefined(node.devices) && !_.isEmpty(node.devices)) {
              if (_.isString(node.devices)) {
                if (node.devices != device) {
                  _d = false;
                }
              } else {
                var _has_d = false;
                _.each(node.devices, function (_v) {
                  if (device == _v) {
                    _has_d = true;
                  }
                });
                if (!_has_d) {
                  _d = false;
                }
              }
            }
            if (_d) {
              var item = that.addItem(node);
              $itemWrapper.append(item);
            }
          });
        });
      },
      switchToDevice: function (device, toggle_button) {
        var that = this;
        var numberDevices = _.size(that.devices);
        if (numberDevices > 1) {
          $(".customify--cb-devices-switcher a", that.container).removeClass("customify--tab-active");
          $(".customify--cb-devices-switcher .switch-to-" + device, that.container).addClass("customify--tab-active");
          $(".customify--device-panel", that.container).addClass("customify--panel-hide");
          $(".customify--device-panel.customify--panel-" + device, that.container).removeClass("customify--panel-hide");
          that.activePanel = device;
        } else {
          $(".customify--cb-devices-switcher a", that.container).addClass("customify--tab-active");
        }
        if (_.isUndefined(toggle_button) || toggle_button) {
          if (device == "desktop") {
            $("#customize-footer-actions .preview-desktop").trigger("click");
          } else {
            $("#customize-footer-actions .preview-mobile").trigger("click");
          }
        }
      },
      addExistingRowsItems: function () {
        var that = this;
        var data = wpcustomize.control(that.controlId).params.value;
        if (!_.isObject(data)) {
          data = {};
        }
        _.each(that.panels, function ($rows, device) {
          var device_data = {};
          if (_.isObject(data[device])) {
            device_data = data[device];
          }
          _.each(device_data, function (items, row_id) {
            if (!_.isUndefined(items)) {
              _.each(items, function (node, index) {
                var item = $('.customify-available-items[data-device="' + device + '"] .grid-stack-item[data-id="' + node.id + '"]').first();
                item.attr("data-gs-width", node.width);
                item.attr("data-gs-x", node.x);
                item.removeClass("item-from-list");
                that.addNewWidget(item, $rows[row_id]);
              });
            }
          });
        });
        that.ready = true;
      },
      focus: function () {
        this.container.on("click", ".customify--cb-item-setting, .customify--cb-item-name, .item-tooltip", function (e) {
          e.preventDefault();
          var section = $(this).data("section") || "";
          //console.log( 'Clicked section' , section );
          var control = $(this).attr("data-control") || "";
          var did = false;
          if (control) {
            if (!_.isUndefined(wpcustomize.control(control))) {
              wpcustomize.control(control).focus();
              did = true;
            }
          }
          if (!did) {
            if (section && !_.isUndefined(wpcustomize.section(section))) {
              wpcustomize.section(section).focus();
              did = true;
            }
          }
        });

        // Focus rows
        this.container.on("click", ".customify--cb-row-settings", function (e) {
          e.preventDefault();
          var id = $(this).attr("data-id") || "";
          var section = options.id + "_" + id;
          if (!_.isUndefined(wpcustomize.section(section))) {
            wpcustomize.section(section).focus();
          }
        });
      },
      remove: function () {
        var that = this;
        $document.on("click", ".customify--device-panel .customify--cb-item-remove", function (e) {
          e.preventDefault();
          var item = $(this).closest(".grid-stack-item");
          var panel = item.closest(".customify--device-panel");
          item.attr("data-gs-width", 1);
          item.attr("data-gs-x", 0);
          item.removeAttr("style");
          $(".customify-available-items", panel).append(item);
          that.updateAllGrids();
          that.save();
        });
      },
      encodeValue: function (value) {
        return encodeURI(JSON.stringify(value));
      },
      decodeValue: function (value) {
        return JSON.parse(decodeURI(value));
      },
      save: function () {
        var that = this;
        if (!that.ready) {
          return;
        }
        var data = {};
        _.each(that.panels, function ($rows, device) {
          data[device] = {};
          _.each($rows, function (row, row_id) {
            var rowData = _.map($(" > .grid-stack-item", row), function (el) {
              el = $(el);
              return {
                x: that.getX(el),
                y: 1,
                width: that.getW(el),
                height: 1,
                id: el.data("id") || ""
              };
            });
            data[device][row_id] = rowData;
          });
        });
        wpcustomize.control(that.controlId).setting.set(that.encodeValue(data));
      },
      showPanel: function () {
        var that = this;
        this.container.removeClass("customify--builder--hide").addClass("customify--builder-show");
        setTimeout(function () {
          var h = that.container.height();
          $("#customize-preview").addClass("cb--preview-panel-show").css({
            bottom: h - 1,
            "margin-top": "0px"
          });
        }, 100);
      },
      hidePanel: function () {
        this.container.removeClass("customify--builder-show");
        $("#customize-preview").removeClass("cb--preview-panel-show").removeAttr("style");
      },
      togglePanel: function () {
        var that = this;
        wpcustomize.state("expandedPanel").bind(function (paneVisible) {
          if (wpcustomize.panel(options.panel).expanded()) {
            $document.trigger("customify_panel_builder_open", [options.panel]);
            top._current_builder_panel = id;
            that.showPanel();
          } else {
            that.hidePanel();
          }
        });
        that.container.on("click", ".customify--panel-close", function (e) {
          e.preventDefault();
          that.container.toggleClass("customify--builder--hide");
          if (that.container.hasClass("customify--builder--hide")) {
            $("#customize-preview").removeClass("cb--preview-panel-show");
          } else {
            $("#customize-preview").addClass("cb--preview-panel-show");
          }
        });
      },
      panelLayoutCSS: function () {
        //wpcustomize.state( 'paneVisible' ).get()
        var sidebarWidth = $("#customize-controls").width();
        if (!wpcustomize.state("paneVisible").get()) {
          sidebarWidth = 0;
        }
        if (is_rtl) {
          this.container.find(".customify--cb-inner").css({
            "margin-right": sidebarWidth
          });
        } else {
          this.container.find(".customify--cb-inner").css({
            "margin-left": sidebarWidth
          });
        }
      },
      init: function (controlId, items, devices) {
        var that = this;
        var template = that.getTemplate();
        var template_id = "tmpl-customify--builder-panel";
        var html = template(options, template_id);
        that.container = $(html);
        $("body .wp-full-overlay").append(that.container);
        that.controlId = controlId;
        that.items = items;
        that.devices = devices;
        if (options.section) {
          wpcustomize.section(options.section).container.addClass("customify--hide");
        }
        that.addDevicePanels();
        that.switchToDevice(that.activePanel);
        that.addAvailableItems();
        that.switchToDevice(that.activePanel);
        that.drag_drop();
        that.focus();
        that.remove();
        that.addExistingRowsItems();
        if (wpcustomize.panel(options.panel).expanded()) {
          that.showPanel();
        } else {
          that.hidePanel();
        }
        wpcustomize.previewedDevice.bind(function (newDevice) {
          if (newDevice === "desktop") {
            that.switchToDevice("desktop", false);
          } else {
            that.switchToDevice("mobile", false);
          }
        });
        that.togglePanel();
        if (wpcustomize.state("paneVisible").get()) {
          that.panelLayoutCSS();
        }
        wpcustomize.state("paneVisible").bind(function () {
          that.panelLayoutCSS();
        });
        $(window).resize(_.throttle(function () {
          that.panelLayoutCSS();
        }, 100));

        // Switch panel.
        that.container.on("click", ".customify--cb-devices-switcher a.switch-to", function (e) {
          e.preventDefault();
          var device = $(this).data("device");
          that.switchToDevice(device);
        });
        $document.trigger("customify_builder_panel_loaded", [id, that]);
      }
    };
    Builder.init(options.control_id, options.items, options.devices);
    return Builder;
  };
})(jQuery);
/******/ })()
;