Fix: Detaching node element surrounded by text elements now merges these text element...
[fnpeditor.git] / views / tabs / tabs.js
1 define([
2 'libs/text!./templates/main.html',
3 'libs/text!./templates/handle.html',
4 'libs/underscore-min',
5 'libs/backbone-min',
6 ], function(mainTemplate, handleTemplate, _, Backbone) {
7     'use strict';
8     
9     var View = Backbone.View.extend({
10         className: 'rng-view-tabs',
11         
12         events: {
13             'click ul a, i': '_onTabTitleClicked'
14         },
15         
16         initialize: function(options) {
17             this.options = options || {};
18             this.template = _.template(mainTemplate);
19             this.handleTemplate = _.template(handleTemplate);
20             this.contents = {};
21             this.selectedTab = null;
22         },
23         
24         render: function() {
25             this.$el.html(this.template());
26             this.nodes = {
27                 tabBar: this.$('.rng-view-tabs-tabBar'),
28                 content: this.$('.rng-view-tabs-content')
29             };
30             
31             if(this.options.stacked) {
32                 this.nodes.tabBar.addClass('nav-stacked nav-pills').removeClass('nav-tabs');
33             }
34             if(this.options.position === 'right') {
35                 this.$el.addClass('tabs-right');
36                 this.nodes.content.addClass('tab-content');
37             }
38             return this;
39         },
40         
41         addTab: function(title, slug, content) {
42             if(this.contents[slug]) {
43                 this.contents[slug].detach();
44             }
45             this.contents[slug] = content;
46             
47             var text = (typeof title === 'string') ? title : (title.text || '');
48             var icon = title.icon || null;
49             
50             if(!this.tabExists(slug))
51                 this.nodes.tabBar.append(this.handleTemplate({text: text, icon: icon, slug: slug}));
52             if(!this.selectedTab)
53                 this.selectTab(slug);
54         },
55         
56         selectTab: function(slug) {
57             if(slug !== this.selectedTab && this.contents[slug]) {
58                 this.trigger('leaving', this.selectedTab);
59                 
60                 if(this.selectedTab) {
61                     var toDetach = this.contents[this.selectedTab];
62                     if(toDetach.onHide)
63                         toDetach.onHide();
64                     toDetach.detach();
65                 }
66                 this.nodes.content.append(this.contents[slug]);
67                 if(this.contents[slug].onShow) {
68                     this.contents[slug].onShow();
69                 }
70                 this.nodes.tabBar.find('.active').removeClass('active');
71                 this.nodes.tabBar.find('a[href="#'+slug+'"]').parent().addClass('active');
72                 
73                 var prevSlug = this.selectedTab;
74                 this.selectedTab = slug;
75                 this.trigger('tabSelected', {slug: slug, prevSlug: prevSlug});
76             }
77         },
78         
79         getAsView: function() {
80             return this.$el;
81         },
82         
83         getCurrentSlug: function() {
84             return this.selectedTab;
85         },
86         
87         tabExists: function(slug) {
88             return this.nodes.tabBar.find('a[href="#'+ slug + '"]').length > 0;
89         },
90         
91         /* Events */
92         
93         _onTabTitleClicked: function(e) {
94             e.preventDefault();
95             var target = $(e.target);
96             if(target.is('i'))
97                 target = target.parent();
98             var slug = target.attr('href').substr(1);
99             this.selectTab(slug);
100         }
101     });
102
103     
104     return {
105         View: View
106     };
107     
108
109 });