summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/lib/utils/bootstrap_linked_tabs.js
blob: a24c71aeab1785baf36ac99b16877be2be41749f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
import $ from 'jquery';

/**
 * Linked Tabs
 *
 * Handles persisting and restores the current tab selection and content.
 * Reusable component for static content.
 *
 * ### Example Markup
 *
 *  <ul class="nav-links tab-links">
 *    <li class="active">
 *      <a data-action="tab1" data-target="#tab1" data-toggle="tab" href="/path/tab1">
 *        Tab 1
 *      </a>
 *    </li>
 *    <li class="groups-tab">
 *      <a data-action="tab2" data-target="#tab2" data-toggle="tab" href="/path/tab2">
 *        Tab 2
 *      </a>
 *    </li>
 *
 *
 *  <div class="tab-content">
 *    <div class="tab-pane" id="tab1">
 *      Tab 1 Content
 *    </div>
 *    <div class="tab-pane" id="tab2">
 *      Tab 2 Content
 *    </div>
 * </div>
 *
 *
 * ### How to use
 *
 *  new LinkedTabs({
 *    action: "#{controller.action_name}",
 *    defaultAction: 'tab1',
 *    parentEl: '.tab-links'
 *  });
 */

export default class LinkedTabs {
  /**
   * Binds the events and activates de default tab.
   *
   * @param  {Object} options
   */
  constructor(options = {}) {
    this.options = options;

    this.defaultAction = this.options.defaultAction;
    this.action = this.options.action || this.defaultAction;

    if (this.action === 'show') {
      this.action = this.defaultAction;
    }

    this.currentLocation = window.location;

    const tabSelector = `${this.options.parentEl} a[data-toggle="tab"]`;

    // since this is a custom event we need jQuery :(
    $(document)
      .off('shown.bs.tab', tabSelector)
      .on('shown.bs.tab', tabSelector, e => this.tabShown(e));

    this.activateTab(this.action);
  }

  /**
   * Handles the `shown.bs.tab` event to set the currect url action.
   *
   * @param  {type} evt
   * @return {Function}
   */
  tabShown(evt) {
    const source = evt.target.getAttribute('href');

    return this.setCurrentAction(source);
  }

  /**
   * Updates the URL with the path that matched the given action.
   *
   * @param  {String} source
   * @return {String}
   */
  setCurrentAction(source) {
    const copySource = source;

    copySource.replace(/\/+$/, '');

    const newState = `${copySource}${this.currentLocation.search}${this.currentLocation.hash}`;

    window.history.replaceState(
      {
        url: newState,
      },
      document.title,
      newState,
    );
    return newState;
  }

  /**
   * Given the current action activates the correct tab.
   * http://getbootstrap.com/javascript/#tab-show
   * Note: Will trigger `shown.bs.tab`
   */
  activateTab() {
    return $(`${this.options.parentEl} a[data-action='${this.action}']`).tab('show');
  }
}