代码之家  ›  专栏  ›  技术社区  ›  dom_ahdigital

如何使用gridstack.js从本地存储设置小部件数据

  •  1
  • dom_ahdigital  · 技术社区  · 6 年前

    脚本

    我有一个仪表板,其中一些小部件被分组到用户可以点击的选项卡中。小部件具有默认的起始位置,包括高度和宽度,但是如果用户移动或调整大小,则使用 gridstack.js )我将新的小部件数据保存到本地存储。

    如果用户在两个选项卡之间单击,则会保留新的小部件位置。

    问题

    当用户刷新页面时,将加载默认的小部件位置,而不是本地存储中的数据。我试着用 getWidgetData() 但运气不好。

    我已经检查了我的本地存储 grid-layout 数据和新位置都存在。

    代码示例

    这里是 Codepen 因为我认为这需要 allow-same-origin ,从而打断了片段。

    // Initialize zurb foundation
    $(document).foundation();
    
    $(function() {
      var grid = $('.grid-stack').data('gridstack');
    
      var options = {
        cellHeight: 40,
        verticalMargin: 28,
        animate: false,
      };
    
      // Initialize grid-stack widgets
      widgetsInit = function(options) {
        $('.grid-stack').gridstack(options);
        getWidgetData(); // Find and set positions from local storage
      }
    
      updateVisibleWidgetHeights = function(options) {
        var targetPanel = '.tabs-panel.is-active';
    
        $(targetPanel + ' .grid-stack .grid-stack-item').each(function(i){
          $(targetPanel + ' .grid-stack').data('gridstack').resize(
            $(targetPanel + ' .grid-stack .grid-stack-item')[i],
            $($(targetPanel + ' .grid-stack .grid-stack-item')[i]).attr('data-gs-width'),
            Math.ceil(($(targetPanel + ' .grid-stack .grid-stack-item .grid-stack-item-content')[i].scrollHeight + $(targetPanel + ' .grid-stack').data('gridstack').opts.verticalMargin) / ($(targetPanel + ' .grid-stack').data('gridstack').cellHeight() + $(targetPanel + ' .grid-stack').data('gridstack').opts.verticalMargin))
          );
        });
      }
    
      updateAllWidgetHeights = function(options) {
        $('.grid-stack .grid-stack-item').each(function(i){
          $('.grid-stack').data('gridstack').resize(
            $('.grid-stack .grid-stack-item')[i],
            $($('.grid-stack .grid-stack-item')[i]).attr('data-gs-width'),
            Math.ceil(($('.grid-stack .grid-stack-item .grid-stack-item-content')[i].scrollHeight + $('.grid-stack').data('gridstack').opts.verticalMargin) / ($('.grid-stack').data('gridstack').cellHeight() + $('.grid-stack').data('gridstack').opts.verticalMargin))
          );
        });
      }
    
      getWidgetData = function() {
        // // Load from local storage
        var serialization = null;
        if (serialization = localStorage.getItem("grid-layout")) {
          _.each(JSON.parse(serialization), function (node) {
            // Update each widget's properties from values in storage
            $('.grid-stack-item[data-custom-id='+ node.id +']').attr({
              'data-gs-x': node.x,
              'data-gs-y': node.y,
              'data-gs-width': node.width,
              'data-gs-height': node.height,
            });
          });
        } else {
          console.log("There was no local storage data to read")
        }
      }
    
      widgetsInit(options);
      updateVisibleWidgetHeights();
    
      $('.grid-stack').on('change', function (event, items) {
        // Save data to local storage
        var res = _.map($('.grid-stack .grid-stack-item'), function (el) {
          el = $(el);
          node = el.data('_gridstack_node');
          return {
            // Grab widget properties
            id: el.attr('data-custom-id'),
            x: node.x,
            y: node.y,
            width: node.width,
            height: node.height
          };
        });
        localStorage.setItem("grid-layout", JSON.stringify(res))
      });
    
      // On tab change update widget heights to the height of the content they contain
      $(document).on('change.zf.tabs', function() {
        updateVisibleWidgetHeights();
      })
    });
    .grid-stack > .grid-stack-item > .grid-stack-item-content {
        background-color: #fff;
        cursor: move;
        border: 1px solid #e3e3e3;
        border-radius: 4px;
    	padding: 1rem;
    }
    <link href="https://cdnjs.cloudflare.com/ajax/libs/gridstack.js/0.4.0/gridstack.min.css" rel="stylesheet"/>
    <link href="https://cdnjs.cloudflare.com/ajax/libs/foundation/6.4.3/css/foundation.min.css" rel="stylesheet"/>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script>
    <script src='https://cdnjs.cloudflare.com/ajax/libs/gridstack.js/0.4.0/gridstack.min.js'></script>
    <script src='https://cdnjs.cloudflare.com/ajax/libs/gridstack.js/0.4.0/gridstack.jQueryUI.min.js'></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/foundation/6.4.3/js/foundation.min.js"></script>
    
    
    <ul class="tabs" data-tabs id="example-tabs" data-deep-link="true" data-update-history="true" data-match-height="false">
      <li class="tabs-title is-active"><a href="#panel1" aria-selected="true">Tab 1</a></li>
      <li class="tabs-title"><a href="#panel2">Tab 2</a></li>
    </ul>
    
    <div class="tabs-content unstyled" data-tabs-content="example-tabs">
      <div class="tabs-panel is-active" id="panel1">
        <div class="grid-stack">
          <div class="grid-stack-item" data-gs-x="0" data-gs-y="0" data-gs-width="4" data-gs-height="2">
            <div class="grid-stack-item-content">#1</div>
          </div>
          <div class="grid-stack-item" data-gs-x="4" data-gs-y="0" data-gs-width="4" data-gs-height="2">
            <div class="grid-stack-item-content">#2</div>
          </div>
          <div class="grid-stack-item" data-gs-x="8" data-gs-y="0"data-gs-width="4" data-gs-height="2">
            <div class="grid-stack-item-content">#3</div>
          </div>
        </div>
      </div>
      <div class="tabs-panel" id="panel2">
        <div class="grid-stack">
          <div class="grid-stack-item" data-gs-x="0" data-gs-y="0" data-gs-width="4" data-gs-height="2">
            <div class="grid-stack-item-content">#4</div>
          </div>
          <div class="grid-stack-item" data-gs-x="4" data-gs-y="0" data-gs-width="4" data-gs-height="2">
            <div class="grid-stack-item-content">#5</div>
          </div>
          <div class="grid-stack-item" data-gs-x="8" data-gs-y="0" data-gs-width="4" data-gs-height="2">
            <div class="grid-stack-item-content">#6</div>
          </div>
        </div>
      </div>
    </div>
    1 回复  |  直到 6 年前
        1
  •  1
  •   Muhammad Omer Aslam    6 年前

    你需要调查一些事情。

    可用的默认示例仅适用于单个实例,而您有多个实例。

    您正在保存和加载 gridstack 一气呵成意味着你没有任何元素的踪迹 grid-stack-item 而且也没有跟踪哪个点属于第一个选项卡或第二个选项卡的实例,

    因此,即使你让它开始工作,它也会尝试将所有6个不同的小部件放在第一个选项卡中,而不是将其加载到各自的选项卡中。

    所以你需要对以下内容进行更改

    • $('.grid-stack').on('change', function (event, items) {

    • getWidgetData()

    • 分配 id custom-data-id 你身上的属性 grid-stack-items 所以它们有一个唯一的标识符

    • 把标签包在一个有ID的容器里 tabs-cotnainer .

    在Gridstack的事件更改中,您应该创建JSON对象,该对象由专门用于存储选项卡的部分中的点组成,如下所示。

    {
      "items": {
        "panel1": [
          {
            "id": "panel1-item1",
            "x": 0,
            "y": 0,
            "width": 4,
            "height": 2
          },
          {
            "id": "panel1-item2",
            "x": 4,
            "y": 0,
            "width": 4,
            "height": 2
          },
          {
            "id": "panel1-item3",
            "x": 8,
            "y": 0,
            "width": 4,
            "height": 2
          }
        ],
        "panel2": [
          {
            "id": "panel2-item1",
            "x": 0,
            "y": 0,
            "width": 4,
            "height": 2
          },
          {
            "id": "panel2-item2",
            "x": 4,
            "y": 0,
            "width": 4,
            "height": 2
          },
          {
            "id": "panel2-item3",
            "x": 8,
            "y": 0,
            "width": 4,
            "height": 2
          }
        ]
      }
    }
    

    替换为以下内容

    $('.grid-stack').on('change', function (event, items) {
        let tabs = $('#tabs-container >ul >li');
        let totalTabs = $('#tabs-container >ul >li').length;
    
        let storagePositions = {
            items: {}
        };
        $.each(tabs, function (index, elem) {
            let panel = $(elem).find('a').attr('href').replace("#", '');
            let stackItems = $('#' + panel + ' .grid-stack .grid-stack-item');
    
            storagePositions.items[panel] = _.map(stackItems, function (el) {
    
                el = $(el);
                node = el.data('_gridstack_node');
                //console.log(node);
    
                return { // Grab widget properties
                    id: el.attr('data-custom-id'),
                    x: node.x,
                    y: node.y,
                    width: node.width,
                    height: node.height
                };
            });
        });
    
        // Save data to local storage
        localStorage.setItem("grid-layout", JSON.stringify(storagePositions))
    });
    

    然后以类似的方式加载标签。

    getWidgetData = function () {
    
        // // Load from local storage
        var serialization = null;
        let tabs = $('#tabs-container >ul >li');
        let totalTabs = $('#tabs-container >ul >li').length;
    
        if (localStorage.getItem("grid-layout") !== null) {
    
            serialization = JSON.parse(localStorage.getItem("grid-layout"));
    
    
    
            $.each(tabs, function (index, elem) {
                let panel = $(elem).find('a').attr('href').replace('#', '');
                let myGrid = $('#' + panel + ' .grid-stack').data('gridstack')
    
                var items = GridStackUI.Utils.sort(serialization.items[panel]);
                _.each(items, function (node) {
    
                    myGrid.update($('div[data-custom-id="' + node.id + '"]'),
                        node.x, node.y, node.width, node.height);
                });
            });
        } else {
            console.log("There was no local storage data to read")
        }
    }
    

    更新后的html如下所示

    <div id="tabs-container">
        <ul class="tabs dashboard-tabs" data-tabs id="example-tabs" data-deep-link="true" data-update-history="true" data-match-height="false">
            <li class="tabs-title is-active">
                <a href="#panel1" aria-selected="true">Tab 1</a>
            </li>
            <li class="tabs-title">
                <a href="#panel2">Tab 2</a>
            </li>
        </ul>
    
        <div class="tabs-content unstyled" data-tabs-content="example-tabs">
            <div class="tabs-panel is-active" id="panel1">
                <div class="grid-stack">
                    <div class="grid-stack-item" data-custom-id="panel1-item1" data-gs-x="0" data-gs-y="0" data-gs-width="4" data-gs-height="2">
                        <div class="grid-stack-item-content">#1</div>
                    </div>
                    <div class="grid-stack-item" data-custom-id="panel1-item2" data-gs-x="4" data-gs-y="0" data-gs-width="4" data-gs-height="2">
                        <div class="grid-stack-item-content">#2</div>
                    </div>
                    <div class="grid-stack-item" data-custom-id="panel1-item3" data-gs-x="8" data-gs-y="0" data-gs-width="4" data-gs-height="2">
                        <div class="grid-stack-item-content">#3</div>
                    </div>
                </div>
            </div>
            <div class="tabs-panel" id="panel2">
                <div class="grid-stack">
                    <div class="grid-stack-item" data-custom-id="panel2-item1" data-gs-x="0" data-gs-y="0" data-gs-width="4" data-gs-height="2">
                        <div class="grid-stack-item-content">#4</div>
                    </div>
                    <div class="grid-stack-item" data-custom-id="panel2-item2" data-gs-x="4" data-gs-y="0" data-gs-width="4" data-gs-height="2">
                        <div class="grid-stack-item-content">#5</div>
                    </div>
                    <div class="grid-stack-item" data-custom-id="panel2-item3" data-gs-x="8" data-gs-y="0" data-gs-width="4" data-gs-height="2">
                        <div class="grid-stack-item-content">#6</div>
                    </div>
                </div>
            </div>
        </div>
    </div>
    

    请看这里的完整工作演示 JSFIDDLE 您可以更新两个选项卡中的位置,然后尝试刷新将显示更新位置的页面。

    注意:只需通过编写 localStorage.removeItem("grid-layout") 在脚本的顶部,他们在第一次运行之后删除了这行。