From cfb03b3d06a3dbd16c6e193a128bb737a0a327fd Mon Sep 17 00:00:00 2001 From: Bryce Johnson Date: Thu, 8 Sep 2016 14:26:43 +0200 Subject: Refactor UserTabs to ES6. --- app/assets/javascripts/user_tabs.js.es6 | 160 ++++++++++++++++++++++++++++++++ 1 file changed, 160 insertions(+) create mode 100644 app/assets/javascripts/user_tabs.js.es6 (limited to 'app/assets/javascripts/user_tabs.js.es6') diff --git a/app/assets/javascripts/user_tabs.js.es6 b/app/assets/javascripts/user_tabs.js.es6 new file mode 100644 index 00000000000..b787700070e --- /dev/null +++ b/app/assets/javascripts/user_tabs.js.es6 @@ -0,0 +1,160 @@ +/* +UserTabs + +Handles persisting and restoring the current tab selection and lazily-loading +content on the Users#show page. + +### Example Markup + + + +
+
+ Activity Content +
+
+ Groups Content +
+
+ Contributed projects content +
+
+ Projects content +
+
+ Snippets content +
+
+ +
+
+ Loading Animation +
+
+*/ +(global => { + class UserTabs { + constructor (opts) { + this.loaded = {}; + this.defaultAction = opts.defaultAction || 'activity'; + this.action = opts.action || 'activity'; + this.$parentEl = $(opts.parentEl) || $(document); + this._location = window.location; + this.$parentEl.find('.nav-links a') + .each((i, navLink) => { + this.loaded[$(navLink).attr('data-action')] = false; + }); + this.actions = Object.keys(this.loaded); + this.bindEvents(); + + if (this.action === 'show') { + this.action = this.defaultAction; + } + + this.activateTab(this.action); + } + + bindEvents() { + return this.$parentEl.off('shown.bs.tab', '.nav-links a[data-toggle="tab"]') + .on('shown.bs.tab', '.nav-links a[data-toggle="tab"]', (event) => this.tabShown(event)); + } + + tabShown(event) { + const $target = $(event.target); + const action = $target.data('action'); + const source = $target.attr('href'); + this.setTab(source, action); + return this.setCurrentAction(action); + } + + activateTab(action) { + return this.$parentEl.find(".nav-links .js-" + action + "-tab a") + .tab('show'); + } + + setTab(source, action) { + if (this.loaded[action]) { + return; + } + if (action === 'activity') { + this.loadActivities(source); + } + if (action === 'groups' || action === 'contributed' || action === 'projects' || action === 'snippets') { + return this.loadTab(source, action); + } + } + + loadTab(source, action) { + return $.ajax({ + beforeSend: () => this.toggleLoading(true), + complete: () => this.toggleLoading(false), + dataType: 'json', + type: 'GET', + url: source + ".json", + success: (data) => { + const tabSelector = 'div#' + action; + this.$parentEl.find(tabSelector).html(data.html); + this.loaded[action] = true; + return gl.utils.localTimeAgo($('.js-timeago', tabSelector)); + } + }); + } + + loadActivities(source) { + if (this.loaded['activity']) { + return; + } + const $calendarWrap = this.$parentEl.find('.user-calendar'); + $calendarWrap.load($calendarWrap.data('href')); + new Activities(); + return this.loaded['activity'] = true; + } + + toggleLoading(status) { + return this.$parentEl.find('.loading-status .loading') + .toggle(status); + } + + setCurrentAction(action) { + const regExp = new RegExp('\/(' + this.actions.join('|') + ')(\.html)?\/?$'); + let new_state = this._location.pathname; + new_state = new_state.replace(/\/+$/, ""); + new_state = new_state.replace(regExp, ''); + if (action !== this.defaultAction) { + new_state += "/" + action; + } + new_state += this._location.search + this._location.hash; + history.replaceState({ + turbolinks: true, + url: new_state + }, document.title, new_state); + return new_state; + }; + } + global.UserTabs = UserTabs; +})(window.gl || (window.gl = {})); -- cgit v1.2.1 From b690c19dbf9a74e356b75e1da63f7dcf237a8c81 Mon Sep 17 00:00:00 2001 From: Bryce Johnson Date: Thu, 8 Sep 2016 17:22:14 +0200 Subject: Use parentheses in IFFE's as per AirBnb styleguide. --- app/assets/javascripts/user_tabs.js.es6 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/assets/javascripts/user_tabs.js.es6') diff --git a/app/assets/javascripts/user_tabs.js.es6 b/app/assets/javascripts/user_tabs.js.es6 index b787700070e..4a69a79118e 100644 --- a/app/assets/javascripts/user_tabs.js.es6 +++ b/app/assets/javascripts/user_tabs.js.es6 @@ -57,7 +57,7 @@ content on the Users#show page. */ -(global => { +((global) => { class UserTabs { constructor (opts) { this.loaded = {}; -- cgit v1.2.1 From 13182a9c5c97b9e104e9efcda203d8b566b72f28 Mon Sep 17 00:00:00 2001 From: Bryce Johnson Date: Fri, 9 Sep 2016 16:57:13 +0200 Subject: Make use of destructuring options, clean up based on feedback. --- app/assets/javascripts/user_tabs.js.es6 | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) (limited to 'app/assets/javascripts/user_tabs.js.es6') diff --git a/app/assets/javascripts/user_tabs.js.es6 b/app/assets/javascripts/user_tabs.js.es6 index 4a69a79118e..1ce0b31c01f 100644 --- a/app/assets/javascripts/user_tabs.js.es6 +++ b/app/assets/javascripts/user_tabs.js.es6 @@ -59,11 +59,11 @@ content on the Users#show page. */ ((global) => { class UserTabs { - constructor (opts) { + constructor ({ defaultAction = 'activity', action = defaultAction, parentEl }) { this.loaded = {}; - this.defaultAction = opts.defaultAction || 'activity'; - this.action = opts.action || 'activity'; - this.$parentEl = $(opts.parentEl) || $(document); + this.defaultAction = defaultAction; + this.action = action; + this.$parentEl = $(parentEl) || $(document); this._location = window.location; this.$parentEl.find('.nav-links a') .each((i, navLink) => { @@ -81,7 +81,7 @@ content on the Users#show page. bindEvents() { return this.$parentEl.off('shown.bs.tab', '.nav-links a[data-toggle="tab"]') - .on('shown.bs.tab', '.nav-links a[data-toggle="tab"]', (event) => this.tabShown(event)); + .on('shown.bs.tab', '.nav-links a[data-toggle="tab"]', event => this.tabShown(event)); } tabShown(event) { @@ -93,7 +93,7 @@ content on the Users#show page. } activateTab(action) { - return this.$parentEl.find(".nav-links .js-" + action + "-tab a") + return this.$parentEl.find(`.nav-links .js-${action}-tab a`) .tab('show'); } @@ -104,7 +104,9 @@ content on the Users#show page. if (action === 'activity') { this.loadActivities(source); } - if (action === 'groups' || action === 'contributed' || action === 'projects' || action === 'snippets') { + + const loadableActions = [ 'groups', 'contributed', 'projects', 'snippets' ]; + if (loadableActions.indexOf(action) > -1) { return this.loadTab(source, action); } } @@ -115,9 +117,9 @@ content on the Users#show page. complete: () => this.toggleLoading(false), dataType: 'json', type: 'GET', - url: source + ".json", + url: `${source}.json`, success: (data) => { - const tabSelector = 'div#' + action; + const tabSelector = `div#${action}`; this.$parentEl.find(tabSelector).html(data.html); this.loaded[action] = true; return gl.utils.localTimeAgo($('.js-timeago', tabSelector)); @@ -141,12 +143,12 @@ content on the Users#show page. } setCurrentAction(action) { - const regExp = new RegExp('\/(' + this.actions.join('|') + ')(\.html)?\/?$'); + const regExp = new RegExp(`\/(${this.actions.join('|')})(\.html)?\/?$`); let new_state = this._location.pathname; - new_state = new_state.replace(/\/+$/, ""); + new_state = new_state.replace(/\/+$/, ''); new_state = new_state.replace(regExp, ''); if (action !== this.defaultAction) { - new_state += "/" + action; + new_state += `/${action}`; } new_state += this._location.search + this._location.hash; history.replaceState({ -- cgit v1.2.1 From b3917d4868120c5a62e4e5525bd3321cb152e2fd Mon Sep 17 00:00:00 2001 From: Bryce Johnson Date: Fri, 9 Sep 2016 18:31:26 +0200 Subject: Set defaults in constructor, in case opts are undefined. --- app/assets/javascripts/user_tabs.js.es6 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'app/assets/javascripts/user_tabs.js.es6') diff --git a/app/assets/javascripts/user_tabs.js.es6 b/app/assets/javascripts/user_tabs.js.es6 index 1ce0b31c01f..7cb38b8ec07 100644 --- a/app/assets/javascripts/user_tabs.js.es6 +++ b/app/assets/javascripts/user_tabs.js.es6 @@ -59,10 +59,10 @@ content on the Users#show page. */ ((global) => { class UserTabs { - constructor ({ defaultAction = 'activity', action = defaultAction, parentEl }) { + constructor ({ defaultAction, action, parentEl }) { this.loaded = {}; - this.defaultAction = defaultAction; - this.action = action; + this.defaultAction = defaultAction || 'activity'; + this.action = action || this.defaultAction; this.$parentEl = $(parentEl) || $(document); this._location = window.location; this.$parentEl.find('.nav-links a') -- cgit v1.2.1 From 8fa3e576a6afa4c424b0e476d6213890491c97c1 Mon Sep 17 00:00:00 2001 From: Bryce Johnson Date: Mon, 19 Sep 2016 16:48:20 +0200 Subject: Remove unneeded semicolon. --- app/assets/javascripts/user_tabs.js.es6 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/assets/javascripts/user_tabs.js.es6') diff --git a/app/assets/javascripts/user_tabs.js.es6 b/app/assets/javascripts/user_tabs.js.es6 index 7cb38b8ec07..63bce0a6f6f 100644 --- a/app/assets/javascripts/user_tabs.js.es6 +++ b/app/assets/javascripts/user_tabs.js.es6 @@ -156,7 +156,7 @@ content on the Users#show page. url: new_state }, document.title, new_state); return new_state; - }; + } } global.UserTabs = UserTabs; })(window.gl || (window.gl = {})); -- cgit v1.2.1