Using jQuery Tabs with Marionette Layouts

2019-02-14 20:44发布

问题:

I'm working on trying to use jquery tabs inside of a Marionette region.

The HTML for a two tabbed area looks like this:

<div id="tabs">
    <ul>
        <li><a href="#tabs-1">Nunc tincidunt</a></li>
        <li><a href="#tabs-2">Proin dolor</a></li>
    </ul>
    <div id="tabs-1">
        <p>Proin elit arcu, rutrum commodo, vehicula tempus, commodo a, risus. Curabitur nec arcu. Donec sollicitudin mi sit amet mauris. Nam elementum quam ullamcorper ante. Etiam aliquet massa et lorem. Mauris dapibus lacus auctor risus. Aenean tempor ullamcorper leo. Vivamus sed magna quis ligula eleifend adipiscing. Duis orci. Aliquam sodales tortor vitae ipsum. Aliquam nulla. Duis aliquam molestie erat. Ut et mauris vel pede varius sollicitudin. Sed ut dolor nec orci tincidunt interdum. Phasellus ipsum. Nunc tristique tempus lectus.</p>
    </div>
    <div id="tabs-2">
        <p>Morbi tincidunt, dui sit amet facilisis feugiat, odio metus gravida ante, ut pharetra massa metus id nunc. Duis scelerisque molestie turpis. Sed fringilla, massa eget luctus malesuada, metus eros molestie lectus, ut tempus eros massa ut dolor. Aenean aliquet fringilla sem. Suspendisse sed ligula in ligula suscipit aliquam. Praesent in eros vestibulum mi adipiscing adipiscing. Morbi facilisis. Curabitur ornare consequat nunc. Aenean vel metus. Ut posuere viverra nulla. Aliquam erat volutpat. Pellentesque convallis. Maecenas feugiat, tellus pellentesque pretium posuere, felis lorem euismod felis, eu ornare leo nisi vel felis. Mauris consectetur tortor et purus.</p>
    </div>
</div>

What I want to do is have an area like this, with multiple "things" in "tabs" -- so adding a < li > and a div to this.

What I'm doing in backbone is grabbing a collection of these "things", and running this on each:

if (thing_type === "content_pane") {
    thing_view = new APP.Views.ThingView({ model : thing_model});
}

//Paint the region
overall_layout.some_region.show(thing_view);

The thing view looks like this:

<div class="thing_view ui-state-active">
    <div class="tabs">
        <ul>
            <li><a href="#tabs-1">{{mustache_variable}}</a></li>
        </ul>
        <span class="thing_panes">
            <div id="tabs-1">
                <p>1roin <a href="http://www.google.com/">Google</a>elit arcu, rutrum commodo, vehicula tempus, commodo a, risus. Curabitur nec arcu. Donec sollicitudin mi sit amet mauris. Nam elementum quam ullamcorper ante. Etiam aliquet massa et lorem. Mauris dapibus lacus auctor risus. Aenean tempor ullamcorper leo. Vivamus sed magna quis ligula eleifend adipiscing. Duis orci. Aliquam sodales tortor vitae ipsum. Aliquam nulla. Duis aliquam molestie erat. Ut et mauris vel pede varius sollicitudin. Sed ut dolor nec orci tincidunt interdum. Phasellus ipsum. Nunc tristique tempus lectus.</p>
            </div>
        </span>
    </div>
</div>

Obviously, right now each time this loop runs it copies over the previous instance.

My question is this -- what is the best way to append a li and a div for each view? Is it a composite view? Is it embedding a region? Collection view? I'm a bit lost on this and would really appreciate some input.

回答1:

You can bind the same collection to multiple views. Here is an example using two collection views. There are other ways I am sure but this is fairly straight forward.

http://jsfiddle.net/puleos/k3Nzz/

Markup:

<div id="tab-container">
    <section id="tabs"></section>
    <section id="tab-content"></section>
</div>
<a id="add-tab" href="#addTab/2">Add a Tab!</a>

<script type="text/html" id="tab-template">
  <a href="#tabs-<%=id%>"><%=tabName%></a>
</script>

<script type="text/html" id="tab-content-template">
    <div id="tabs-<%=id%>">
      <p><%=content%></p>
    </div>
</script>

JS

var App = new Marionette.Application();

App.addRegions({
    "tabs": "#tabs",
    "tabContent": "#tab-content"
});

App.on("initialize:after", function() {
    Backbone.history.start();
});

App.module("TabModule", function(Mod, App, Backbone, Marionette, $, _){
    var tabsCollection = new Backbone.Collection([
          { id: 1,
            tabName: "tab1",
            content: "tab1 content elit arcu, rutrum commodo, vehicula tempus, commodo a, risus. Curabitur nec arcu. Donec sollicitudin mi sit amet mauris. Nam elementum quam ullamcorper ante. Etiam aliquet massa et lorem" 
            },
        { id: 2,
            tabName: "tab2",
            content: "tab2 content elit arcu, rutrum commodo, vehicula tempus, commodo a, risus. Curabitur nec arcu. Donec sollicitudin mi sit amet mauris. Nam elementum quam ullamcorper ante. Etiam aliquet massa et lorem" 
            },
    ]);

    var TabItem = Marionette.ItemView.extend({
        tagName: "li",
        template: "#tab-template"
    });

    var TabView = Marionette.CollectionView.extend({
        itemView: TabItem,
        itemViewContainer: "ul",
        tagName: "ul"
    });

    var TabContentItem = Marionette.ItemView.extend({
        tagName: "div",
        template: "#tab-content-template"
    });

    var TabContentView = Marionette.CollectionView.extend({
        itemView: TabContentItem,
        itemViewContainer: "div"
    });

    // Define a controller to run this module
    // --------------------------------------
    var Router = Marionette.AppRouter.extend({
        appRoutes: {
        "addTab/:tab": "addTab"
        },
    });

    var Controller = Marionette.Controller.extend({

        initialize: function(options){
            this.region = options.region
        },
        addTab: function(tab){
            var tabCount = tabsCollection.length + 1;
            tabsCollection.add({
                id: tabCount, 
                tabName: "tab" + tabCount,
                content: "tab" + tabCount + "elit arcu..." 
            });

            $("#tab-container").tabs("refresh");
            $("#add-tab").attr("href", "#addTab/"+ tabCount);
        },
        start: function(){
            var tabView = new TabView({
                collection: tabsCollection    
            });
            var tabContentView = new TabContentView({
                collection: tabsCollection    
            });

            App.tabs.show(tabView);
            App.tabContent.show(tabContentView);
            $("#tab-container").tabs();
        }

    });

    Mod.addInitializer(function(){
        Mod.controller = new Controller();
        Mod.router = new Router({
            controller: Mod.controller
        });
        Mod.controller.start();
    });
});

// Start the app
// -------------
App.start();