From c06dad62e1004eb5b4f2251a233f740d3fa2a5c2 Mon Sep 17 00:00:00 2001 From: Mike Greiling Date: Wed, 5 Jul 2017 17:20:41 +0000 Subject: [PATCH] Remove IIFEs around several javascript classes --- .../javascripts/signin_tabs_memoizer.js | 90 +++--- app/assets/javascripts/single_file_diff.js | 168 +++++----- app/assets/javascripts/smart_interval.js | 289 +++++++++--------- app/assets/javascripts/snippets_list.js | 16 +- app/assets/javascripts/star.js | 50 ++- app/assets/javascripts/subscription.js | 84 +++-- app/assets/javascripts/subscription_select.js | 63 ++-- app/assets/javascripts/syntax_highlight.js | 27 +- app/assets/javascripts/tree.js | 118 ++++--- app/assets/javascripts/user.js | 57 ++-- app/assets/javascripts/user_tabs.js | 213 ++++++------- app/assets/javascripts/username_validator.js | 224 +++++++------- app/assets/javascripts/visibility_select.js | 43 ++- app/assets/javascripts/wikis.js | 107 ++++--- app/assets/javascripts/zen_mode.js | 115 ++++--- 15 files changed, 821 insertions(+), 843 deletions(-) diff --git a/app/assets/javascripts/signin_tabs_memoizer.js b/app/assets/javascripts/signin_tabs_memoizer.js index 2587facc582..3997a695d15 100644 --- a/app/assets/javascripts/signin_tabs_memoizer.js +++ b/app/assets/javascripts/signin_tabs_memoizer.js @@ -2,56 +2,54 @@ /* eslint no-new: "off" */ import AccessorUtilities from './lib/utils/accessor'; -((global) => { - /** - * Memorize the last selected tab after reloading a page. - * Does that setting the current selected tab in the localStorage - */ - class ActiveTabMemoizer { - constructor({ currentTabKey = 'current_signin_tab', tabSelector = 'ul.nav-tabs' } = {}) { - this.currentTabKey = currentTabKey; - this.tabSelector = tabSelector; - this.isLocalStorageAvailable = AccessorUtilities.isLocalStorageAccessSafe(); +/** + * Memorize the last selected tab after reloading a page. + * Does that setting the current selected tab in the localStorage + */ +class ActiveTabMemoizer { + constructor({ currentTabKey = 'current_signin_tab', tabSelector = 'ul.nav-tabs' } = {}) { + this.currentTabKey = currentTabKey; + this.tabSelector = tabSelector; + this.isLocalStorageAvailable = AccessorUtilities.isLocalStorageAccessSafe(); - this.bootstrap(); - } + this.bootstrap(); + } - bootstrap() { - const tabs = document.querySelectorAll(this.tabSelector); - if (tabs.length > 0) { - tabs[0].addEventListener('click', (e) => { - if (e.target && e.target.nodeName === 'A') { - const anchorName = e.target.getAttribute('href'); - this.saveData(anchorName); - } - }); - } - - this.showTab(); - } - - showTab() { - const anchorName = this.readData(); - if (anchorName) { - const tab = document.querySelector(`${this.tabSelector} a[href="${anchorName}"]`); - if (tab) { - tab.click(); + bootstrap() { + const tabs = document.querySelectorAll(this.tabSelector); + if (tabs.length > 0) { + tabs[0].addEventListener('click', (e) => { + if (e.target && e.target.nodeName === 'A') { + const anchorName = e.target.getAttribute('href'); + this.saveData(anchorName); } + }); + } + + this.showTab(); + } + + showTab() { + const anchorName = this.readData(); + if (anchorName) { + const tab = document.querySelector(`${this.tabSelector} a[href="${anchorName}"]`); + if (tab) { + tab.click(); } } - - saveData(val) { - if (!this.isLocalStorageAvailable) return undefined; - - return window.localStorage.setItem(this.currentTabKey, val); - } - - readData() { - if (!this.isLocalStorageAvailable) return null; - - return window.localStorage.getItem(this.currentTabKey); - } } - global.ActiveTabMemoizer = ActiveTabMemoizer; -})(window); + saveData(val) { + if (!this.isLocalStorageAvailable) return undefined; + + return window.localStorage.setItem(this.currentTabKey, val); + } + + readData() { + if (!this.isLocalStorageAvailable) return null; + + return window.localStorage.getItem(this.currentTabKey); + } +} + +window.ActiveTabMemoizer = ActiveTabMemoizer; diff --git a/app/assets/javascripts/single_file_diff.js b/app/assets/javascripts/single_file_diff.js index 9316a2af0b7..00d04ce0c33 100644 --- a/app/assets/javascripts/single_file_diff.js +++ b/app/assets/javascripts/single_file_diff.js @@ -2,99 +2,97 @@ import FilesCommentButton from './files_comment_button'; -(function() { - window.SingleFileDiff = (function() { - var COLLAPSED_HTML, ERROR_HTML, LOADING_HTML, WRAPPER; +window.SingleFileDiff = (function() { + var COLLAPSED_HTML, ERROR_HTML, LOADING_HTML, WRAPPER; - WRAPPER = '
'; + WRAPPER = '
'; - LOADING_HTML = ''; + LOADING_HTML = ''; - ERROR_HTML = '
Could not load diff
'; + ERROR_HTML = '
Could not load diff
'; - COLLAPSED_HTML = '
This diff is collapsed. Click to expand it.
'; + COLLAPSED_HTML = '
This diff is collapsed. Click to expand it.
'; - function SingleFileDiff(file) { - this.file = file; - this.toggleDiff = this.toggleDiff.bind(this); - this.content = $('.diff-content', this.file); - this.$toggleIcon = $('.diff-toggle-caret', this.file); - this.diffForPath = this.content.find('[data-diff-for-path]').data('diff-for-path'); - this.isOpen = !this.diffForPath; - if (this.diffForPath) { - this.collapsedContent = this.content; - this.loadingContent = $(WRAPPER).addClass('loading').html(LOADING_HTML).hide(); - this.content = null; - this.collapsedContent.after(this.loadingContent); - this.$toggleIcon.addClass('fa-caret-right'); - } else { - this.collapsedContent = $(WRAPPER).html(COLLAPSED_HTML).hide(); - this.content.after(this.collapsedContent); - this.$toggleIcon.addClass('fa-caret-down'); - } - - $('.js-file-title, .click-to-expand', this.file).on('click', (function (e) { - this.toggleDiff($(e.target)); - }).bind(this)); + function SingleFileDiff(file) { + this.file = file; + this.toggleDiff = this.toggleDiff.bind(this); + this.content = $('.diff-content', this.file); + this.$toggleIcon = $('.diff-toggle-caret', this.file); + this.diffForPath = this.content.find('[data-diff-for-path]').data('diff-for-path'); + this.isOpen = !this.diffForPath; + if (this.diffForPath) { + this.collapsedContent = this.content; + this.loadingContent = $(WRAPPER).addClass('loading').html(LOADING_HTML).hide(); + this.content = null; + this.collapsedContent.after(this.loadingContent); + this.$toggleIcon.addClass('fa-caret-right'); + } else { + this.collapsedContent = $(WRAPPER).html(COLLAPSED_HTML).hide(); + this.content.after(this.collapsedContent); + this.$toggleIcon.addClass('fa-caret-down'); } - SingleFileDiff.prototype.toggleDiff = function($target, cb) { - if (!$target.hasClass('js-file-title') && !$target.hasClass('click-to-expand') && !$target.hasClass('diff-toggle-caret')) return; - this.isOpen = !this.isOpen; - if (!this.isOpen && !this.hasError) { - this.content.hide(); - this.$toggleIcon.addClass('fa-caret-right').removeClass('fa-caret-down'); - this.collapsedContent.show(); - if (typeof gl.diffNotesCompileComponents !== 'undefined') { - gl.diffNotesCompileComponents(); - } - } else if (this.content) { - this.collapsedContent.hide(); - this.content.show(); - this.$toggleIcon.addClass('fa-caret-down').removeClass('fa-caret-right'); - if (typeof gl.diffNotesCompileComponents !== 'undefined') { - gl.diffNotesCompileComponents(); - } - } else { - this.$toggleIcon.addClass('fa-caret-down').removeClass('fa-caret-right'); - return this.getContentHTML(cb); - } - }; + $('.js-file-title, .click-to-expand', this.file).on('click', (function (e) { + this.toggleDiff($(e.target)); + }).bind(this)); + } - SingleFileDiff.prototype.getContentHTML = function(cb) { + SingleFileDiff.prototype.toggleDiff = function($target, cb) { + if (!$target.hasClass('js-file-title') && !$target.hasClass('click-to-expand') && !$target.hasClass('diff-toggle-caret')) return; + this.isOpen = !this.isOpen; + if (!this.isOpen && !this.hasError) { + this.content.hide(); + this.$toggleIcon.addClass('fa-caret-right').removeClass('fa-caret-down'); + this.collapsedContent.show(); + if (typeof gl.diffNotesCompileComponents !== 'undefined') { + gl.diffNotesCompileComponents(); + } + } else if (this.content) { this.collapsedContent.hide(); - this.loadingContent.show(); - $.get(this.diffForPath, (function(_this) { - return function(data) { - _this.loadingContent.hide(); - if (data.html) { - _this.content = $(data.html); - _this.content.syntaxHighlight(); - } else { - _this.hasError = true; - _this.content = $(ERROR_HTML); - } - _this.collapsedContent.after(_this.content); - - if (typeof gl.diffNotesCompileComponents !== 'undefined') { - gl.diffNotesCompileComponents(); - } - - FilesCommentButton.init($(_this.file)); - - if (cb) cb(); - }; - })(this)); - }; - - return SingleFileDiff; - })(); - - $.fn.singleFileDiff = function() { - return this.each(function() { - if (!$.data(this, 'singleFileDiff')) { - return $.data(this, 'singleFileDiff', new window.SingleFileDiff(this)); + this.content.show(); + this.$toggleIcon.addClass('fa-caret-down').removeClass('fa-caret-right'); + if (typeof gl.diffNotesCompileComponents !== 'undefined') { + gl.diffNotesCompileComponents(); } - }); + } else { + this.$toggleIcon.addClass('fa-caret-down').removeClass('fa-caret-right'); + return this.getContentHTML(cb); + } }; -}).call(window); + + SingleFileDiff.prototype.getContentHTML = function(cb) { + this.collapsedContent.hide(); + this.loadingContent.show(); + $.get(this.diffForPath, (function(_this) { + return function(data) { + _this.loadingContent.hide(); + if (data.html) { + _this.content = $(data.html); + _this.content.syntaxHighlight(); + } else { + _this.hasError = true; + _this.content = $(ERROR_HTML); + } + _this.collapsedContent.after(_this.content); + + if (typeof gl.diffNotesCompileComponents !== 'undefined') { + gl.diffNotesCompileComponents(); + } + + FilesCommentButton.init($(_this.file)); + + if (cb) cb(); + }; + })(this)); + }; + + return SingleFileDiff; +})(); + +$.fn.singleFileDiff = function() { + return this.each(function() { + if (!$.data(this, 'singleFileDiff')) { + return $.data(this, 'singleFileDiff', new window.SingleFileDiff(this)); + } + }); +}; diff --git a/app/assets/javascripts/smart_interval.js b/app/assets/javascripts/smart_interval.js index d1bdc353be2..2bf7a3a5d61 100644 --- a/app/assets/javascripts/smart_interval.js +++ b/app/assets/javascripts/smart_interval.js @@ -1,158 +1,157 @@ -/* -* Instances of SmartInterval extend the functionality of `setInterval`, make it configurable -* and controllable by a public API. -* -* */ +/** + * Instances of SmartInterval extend the functionality of `setInterval`, make it configurable + * and controllable by a public API. + */ -(() => { - class SmartInterval { - /** - * @param { function } opts.callback Function to be called on each iteration (required) - * @param { milliseconds } opts.startingInterval `currentInterval` is set to this initially - * @param { milliseconds } opts.maxInterval `currentInterval` will be incremented to this - * @param { milliseconds } opts.hiddenInterval `currentInterval` is set to this - * when the page is hidden - * @param { integer } opts.incrementByFactorOf `currentInterval` is incremented by this factor - * @param { boolean } opts.lazyStart Configure if timer is initialized on - * instantiation or lazily - * @param { boolean } opts.immediateExecution Configure if callback should - * be executed before the first interval. - */ - constructor(opts = {}) { - this.cfg = { - callback: opts.callback, - startingInterval: opts.startingInterval, - maxInterval: opts.maxInterval, - hiddenInterval: opts.hiddenInterval, - incrementByFactorOf: opts.incrementByFactorOf, - lazyStart: opts.lazyStart, - immediateExecution: opts.immediateExecution, - }; +class SmartInterval { + /** + * @param { function } opts.callback Function to be called on each iteration (required) + * @param { milliseconds } opts.startingInterval `currentInterval` is set to this initially + * @param { milliseconds } opts.maxInterval `currentInterval` will be incremented to this + * @param { milliseconds } opts.hiddenInterval `currentInterval` is set to this + * when the page is hidden + * @param { integer } opts.incrementByFactorOf `currentInterval` is incremented by this factor + * @param { boolean } opts.lazyStart Configure if timer is initialized on + * instantiation or lazily + * @param { boolean } opts.immediateExecution Configure if callback should + * be executed before the first interval. + */ + constructor(opts = {}) { + this.cfg = { + callback: opts.callback, + startingInterval: opts.startingInterval, + maxInterval: opts.maxInterval, + hiddenInterval: opts.hiddenInterval, + incrementByFactorOf: opts.incrementByFactorOf, + lazyStart: opts.lazyStart, + immediateExecution: opts.immediateExecution, + }; - this.state = { - intervalId: null, - currentInterval: this.cfg.startingInterval, - pageVisibility: 'visible', - }; + this.state = { + intervalId: null, + currentInterval: this.cfg.startingInterval, + pageVisibility: 'visible', + }; - this.initInterval(); + this.initInterval(); + } + + /* public */ + + start() { + const cfg = this.cfg; + const state = this.state; + + if (cfg.immediateExecution) { + cfg.immediateExecution = false; + cfg.callback(); } - /* public */ - start() { - const cfg = this.cfg; - const state = this.state; + state.intervalId = window.setInterval(() => { + cfg.callback(); - if (cfg.immediateExecution) { - cfg.immediateExecution = false; - cfg.callback(); + if (this.getCurrentInterval() === cfg.maxInterval) { + return; } - state.intervalId = window.setInterval(() => { - cfg.callback(); + this.incrementInterval(); + this.resume(); + }, this.getCurrentInterval()); + } - if (this.getCurrentInterval() === cfg.maxInterval) { - return; - } + // cancel the existing timer, setting the currentInterval back to startingInterval + cancel() { + this.setCurrentInterval(this.cfg.startingInterval); + this.stopTimer(); + } - this.incrementInterval(); - this.resume(); - }, this.getCurrentInterval()); - } - - // cancel the existing timer, setting the currentInterval back to startingInterval - cancel() { - this.setCurrentInterval(this.cfg.startingInterval); - this.stopTimer(); - } - - onVisibilityHidden() { - if (this.cfg.hiddenInterval) { - this.setCurrentInterval(this.cfg.hiddenInterval); - this.resume(); - } else { - this.cancel(); - } - } - - // start a timer, using the existing interval - resume() { - this.stopTimer(); // stop exsiting timer, in case timer was not previously stopped - this.start(); - } - - onVisibilityVisible() { + onVisibilityHidden() { + if (this.cfg.hiddenInterval) { + this.setCurrentInterval(this.cfg.hiddenInterval); + this.resume(); + } else { this.cancel(); - this.start(); - } - - destroy() { - this.cancel(); - document.removeEventListener('visibilitychange', this.handleVisibilityChange); - $(document).off('visibilitychange').off('beforeunload'); - } - - /* private */ - - initInterval() { - const cfg = this.cfg; - - if (!cfg.lazyStart) { - this.start(); - } - - this.initVisibilityChangeHandling(); - this.initPageUnloadHandling(); - } - - initVisibilityChangeHandling() { - // cancel interval when tab no longer shown (prevents cached pages from polling) - document.addEventListener('visibilitychange', this.handleVisibilityChange.bind(this)); - } - - initPageUnloadHandling() { - // TODO: Consider refactoring in light of turbolinks removal. - // prevent interval continuing after page change, when kept in cache by Turbolinks - $(document).on('beforeunload', () => this.cancel()); - } - - handleVisibilityChange(e) { - this.state.pageVisibility = e.target.visibilityState; - const intervalAction = this.isPageVisible() ? - this.onVisibilityVisible : - this.onVisibilityHidden; - - intervalAction.apply(this); - } - - getCurrentInterval() { - return this.state.currentInterval; - } - - setCurrentInterval(newInterval) { - this.state.currentInterval = newInterval; - } - - incrementInterval() { - const cfg = this.cfg; - const currentInterval = this.getCurrentInterval(); - if (cfg.hiddenInterval && !this.isPageVisible()) return; - let nextInterval = currentInterval * cfg.incrementByFactorOf; - - if (nextInterval > cfg.maxInterval) { - nextInterval = cfg.maxInterval; - } - - this.setCurrentInterval(nextInterval); - } - - isPageVisible() { return this.state.pageVisibility === 'visible'; } - - stopTimer() { - const state = this.state; - - state.intervalId = window.clearInterval(state.intervalId); } } - gl.SmartInterval = SmartInterval; -})(window.gl || (window.gl = {})); + + // start a timer, using the existing interval + resume() { + this.stopTimer(); // stop exsiting timer, in case timer was not previously stopped + this.start(); + } + + onVisibilityVisible() { + this.cancel(); + this.start(); + } + + destroy() { + this.cancel(); + document.removeEventListener('visibilitychange', this.handleVisibilityChange); + $(document).off('visibilitychange').off('beforeunload'); + } + + /* private */ + + initInterval() { + const cfg = this.cfg; + + if (!cfg.lazyStart) { + this.start(); + } + + this.initVisibilityChangeHandling(); + this.initPageUnloadHandling(); + } + + initVisibilityChangeHandling() { + // cancel interval when tab no longer shown (prevents cached pages from polling) + document.addEventListener('visibilitychange', this.handleVisibilityChange.bind(this)); + } + + initPageUnloadHandling() { + // TODO: Consider refactoring in light of turbolinks removal. + // prevent interval continuing after page change, when kept in cache by Turbolinks + $(document).on('beforeunload', () => this.cancel()); + } + + handleVisibilityChange(e) { + this.state.pageVisibility = e.target.visibilityState; + const intervalAction = this.isPageVisible() ? + this.onVisibilityVisible : + this.onVisibilityHidden; + + intervalAction.apply(this); + } + + getCurrentInterval() { + return this.state.currentInterval; + } + + setCurrentInterval(newInterval) { + this.state.currentInterval = newInterval; + } + + incrementInterval() { + const cfg = this.cfg; + const currentInterval = this.getCurrentInterval(); + if (cfg.hiddenInterval && !this.isPageVisible()) return; + let nextInterval = currentInterval * cfg.incrementByFactorOf; + + if (nextInterval > cfg.maxInterval) { + nextInterval = cfg.maxInterval; + } + + this.setCurrentInterval(nextInterval); + } + + isPageVisible() { return this.state.pageVisibility === 'visible'; } + + stopTimer() { + const state = this.state; + + state.intervalId = window.clearInterval(state.intervalId); + } +} + +window.gl.SmartInterval = SmartInterval; diff --git a/app/assets/javascripts/snippets_list.js b/app/assets/javascripts/snippets_list.js index 2128007113f..da7b9e08447 100644 --- a/app/assets/javascripts/snippets_list.js +++ b/app/assets/javascripts/snippets_list.js @@ -1,13 +1,9 @@ /* eslint-disable arrow-parens, no-param-reassign, space-before-function-paren, func-names, no-var, max-len */ -(global => { - global.gl = global.gl || {}; +window.gl.SnippetsList = function() { + var $holder = $('.snippets-list-holder'); - gl.SnippetsList = function() { - var $holder = $('.snippets-list-holder'); - - $holder.find('.pagination').on('ajax:success', (e, data) => { - $holder.replaceWith(data.html); - }); - }; -})(window); + $holder.find('.pagination').on('ajax:success', (e, data) => { + $holder.replaceWith(data.html); + }); +}; diff --git a/app/assets/javascripts/star.js b/app/assets/javascripts/star.js index c75b44cc2fd..840ae1edd9d 100644 --- a/app/assets/javascripts/star.js +++ b/app/assets/javascripts/star.js @@ -1,30 +1,28 @@ /* eslint-disable func-names, space-before-function-paren, wrap-iife, no-unused-vars, one-var, no-var, one-var-declaration-per-line, prefer-arrow-callback, no-new, max-len */ /* global Flash */ -(function() { - this.Star = (function() { - function Star() { - $('.project-home-panel .toggle-star').on('ajax:success', function(e, data, status, xhr) { - var $starIcon, $starSpan, $this, toggleStar; - $this = $(this); - $starSpan = $this.find('span'); - $starIcon = $this.find('i'); - toggleStar = function(isStarred) { - $this.parent().find('.star-count').text(data.star_count); - if (isStarred) { - $starSpan.removeClass('starred').text('Star'); - $starIcon.removeClass('fa-star').addClass('fa-star-o'); - } else { - $starSpan.addClass('starred').text('Unstar'); - $starIcon.removeClass('fa-star-o').addClass('fa-star'); - } - }; - toggleStar($starSpan.hasClass('starred')); - }).on('ajax:error', function(e, xhr, status, error) { - new Flash('Star toggle failed. Try again later.', 'alert'); - }); - } +window.Star = (function() { + function Star() { + $('.project-home-panel .toggle-star').on('ajax:success', function(e, data, status, xhr) { + var $starIcon, $starSpan, $this, toggleStar; + $this = $(this); + $starSpan = $this.find('span'); + $starIcon = $this.find('i'); + toggleStar = function(isStarred) { + $this.parent().find('.star-count').text(data.star_count); + if (isStarred) { + $starSpan.removeClass('starred').text('Star'); + $starIcon.removeClass('fa-star').addClass('fa-star-o'); + } else { + $starSpan.addClass('starred').text('Unstar'); + $starIcon.removeClass('fa-star-o').addClass('fa-star'); + } + }; + toggleStar($starSpan.hasClass('starred')); + }).on('ajax:error', function(e, xhr, status, error) { + new Flash('Star toggle failed. Try again later.', 'alert'); + }); + } - return Star; - })(); -}).call(window); + return Star; +})(); diff --git a/app/assets/javascripts/subscription.js b/app/assets/javascripts/subscription.js index 5f9a3e00c22..bb4d68fcd49 100644 --- a/app/assets/javascripts/subscription.js +++ b/app/assets/javascripts/subscription.js @@ -1,47 +1,45 @@ -(() => { - class Subscription { - constructor(containerElm) { - this.containerElm = containerElm; +class Subscription { + constructor(containerElm) { + this.containerElm = containerElm; - const subscribeButton = containerElm.querySelector('.js-subscribe-button'); - if (subscribeButton) { - // remove class so we don't bind twice - subscribeButton.classList.remove('js-subscribe-button'); - subscribeButton.addEventListener('click', this.toggleSubscription.bind(this)); - } - } - - toggleSubscription(event) { - const button = event.currentTarget; - const buttonSpan = button.querySelector('span'); - if (!buttonSpan || button.classList.contains('disabled')) { - return; - } - button.classList.add('disabled'); - - const isSubscribed = buttonSpan.innerHTML.trim().toLowerCase() !== 'subscribe'; - const toggleActionUrl = this.containerElm.dataset.url; - - $.post(toggleActionUrl, () => { - button.classList.remove('disabled'); - - // hack to allow this to work with the issue boards Vue object - if (document.querySelector('html').classList.contains('issue-boards-page')) { - gl.issueBoards.boardStoreIssueSet( - 'subscribed', - !gl.issueBoards.BoardsStore.detail.issue.subscribed, - ); - } else { - buttonSpan.innerHTML = isSubscribed ? 'Subscribe' : 'Unsubscribe'; - } - }); - } - - static bindAll(selector) { - [].forEach.call(document.querySelectorAll(selector), elm => new Subscription(elm)); + const subscribeButton = containerElm.querySelector('.js-subscribe-button'); + if (subscribeButton) { + // remove class so we don't bind twice + subscribeButton.classList.remove('js-subscribe-button'); + subscribeButton.addEventListener('click', this.toggleSubscription.bind(this)); } } - window.gl = window.gl || {}; - window.gl.Subscription = Subscription; -})(); + toggleSubscription(event) { + const button = event.currentTarget; + const buttonSpan = button.querySelector('span'); + if (!buttonSpan || button.classList.contains('disabled')) { + return; + } + button.classList.add('disabled'); + + const isSubscribed = buttonSpan.innerHTML.trim().toLowerCase() !== 'subscribe'; + const toggleActionUrl = this.containerElm.dataset.url; + + $.post(toggleActionUrl, () => { + button.classList.remove('disabled'); + + // hack to allow this to work with the issue boards Vue object + if (document.querySelector('html').classList.contains('issue-boards-page')) { + gl.issueBoards.boardStoreIssueSet( + 'subscribed', + !gl.issueBoards.BoardsStore.detail.issue.subscribed, + ); + } else { + buttonSpan.innerHTML = isSubscribed ? 'Subscribe' : 'Unsubscribe'; + } + }); + } + + static bindAll(selector) { + [].forEach.call(document.querySelectorAll(selector), elm => new Subscription(elm)); + } +} + +window.gl = window.gl || {}; +window.gl.Subscription = Subscription; diff --git a/app/assets/javascripts/subscription_select.js b/app/assets/javascripts/subscription_select.js index 0cd591c7320..a48434181b6 100644 --- a/app/assets/javascripts/subscription_select.js +++ b/app/assets/javascripts/subscription_select.js @@ -1,34 +1,33 @@ /* eslint-disable func-names, space-before-function-paren, wrap-iife, no-var, quotes, object-shorthand, no-unused-vars, no-shadow, one-var, one-var-declaration-per-line, comma-dangle, max-len */ -(function() { - this.SubscriptionSelect = (function() { - function SubscriptionSelect() { - $('.js-subscription-event').each(function(i, el) { - var fieldName; - fieldName = $(el).data("field-name"); - return $(el).glDropdown({ - selectable: true, - fieldName: fieldName, - toggleLabel: (function(_this) { - return function(selected, el, instance) { - var $item, label; - label = 'Subscription'; - $item = instance.dropdown.find('.is-active'); - if ($item.length) { - label = $item.text(); - } - return label; - }; - })(this), - clicked: function(options) { - return options.e.preventDefault(); - }, - id: function(obj, el) { - return $(el).data("id"); - } - }); - }); - } - return SubscriptionSelect; - })(); -}).call(window); +window.SubscriptionSelect = (function() { + function SubscriptionSelect() { + $('.js-subscription-event').each(function(i, el) { + var fieldName; + fieldName = $(el).data("field-name"); + return $(el).glDropdown({ + selectable: true, + fieldName: fieldName, + toggleLabel: (function(_this) { + return function(selected, el, instance) { + var $item, label; + label = 'Subscription'; + $item = instance.dropdown.find('.is-active'); + if ($item.length) { + label = $item.text(); + } + return label; + }; + })(this), + clicked: function(options) { + return options.e.preventDefault(); + }, + id: function(obj, el) { + return $(el).data("id"); + } + }); + }); + } + + return SubscriptionSelect; +})(); diff --git a/app/assets/javascripts/syntax_highlight.js b/app/assets/javascripts/syntax_highlight.js index 7c063fae045..662d6b36c16 100644 --- a/app/assets/javascripts/syntax_highlight.js +++ b/app/assets/javascripts/syntax_highlight.js @@ -9,19 +9,18 @@ // //
// -(function() { - $.fn.syntaxHighlight = function() { - var $children; - if ($(this).hasClass('js-syntax-highlight')) { - // Given the element itself, apply highlighting - return $(this).addClass(gon.user_color_scheme); - } else { - // Given a parent element, recurse to any of its applicable children - $children = $(this).find('.js-syntax-highlight'); - if ($children.length) { - return $children.syntaxHighlight(); - } +$.fn.syntaxHighlight = function() { + var $children; + + if ($(this).hasClass('js-syntax-highlight')) { + // Given the element itself, apply highlighting + return $(this).addClass(gon.user_color_scheme); + } else { + // Given a parent element, recurse to any of its applicable children + $children = $(this).find('.js-syntax-highlight'); + if ($children.length) { + return $children.syntaxHighlight(); } - }; -}).call(window); + } +}; diff --git a/app/assets/javascripts/tree.js b/app/assets/javascripts/tree.js index 76a821c7a17..77ae6109bc6 100644 --- a/app/assets/javascripts/tree.js +++ b/app/assets/javascripts/tree.js @@ -1,68 +1,66 @@ /* eslint-disable func-names, space-before-function-paren, wrap-iife, max-len, quotes, consistent-return, no-var, one-var, one-var-declaration-per-line, no-else-return, prefer-arrow-callback, max-len */ -(function() { - this.TreeView = (function() { - function TreeView() { - this.initKeyNav(); - // Code browser tree slider - // Make the entire tree-item row clickable, but not if clicking another link (like a commit message) - $(".tree-content-holder .tree-item").on('click', function(e) { - var $clickedEl, path; - $clickedEl = $(e.target); - path = $('.tree-item-file-name a', this).attr('href'); - if (!$clickedEl.is('a') && !$clickedEl.is('.str-truncated')) { - if (e.metaKey || e.which === 2) { - e.preventDefault(); - return window.open(path, '_blank'); - } else { - return gl.utils.visitUrl(path); - } +window.TreeView = (function() { + function TreeView() { + this.initKeyNav(); + // Code browser tree slider + // Make the entire tree-item row clickable, but not if clicking another link (like a commit message) + $(".tree-content-holder .tree-item").on('click', function(e) { + var $clickedEl, path; + $clickedEl = $(e.target); + path = $('.tree-item-file-name a', this).attr('href'); + if (!$clickedEl.is('a') && !$clickedEl.is('.str-truncated')) { + if (e.metaKey || e.which === 2) { + e.preventDefault(); + return window.open(path, '_blank'); + } else { + return gl.utils.visitUrl(path); } - }); - // Show the "Loading commit data" for only the first element - $('span.log_loading:first').removeClass('hide'); - } + } + }); + // Show the "Loading commit data" for only the first element + $('span.log_loading:first').removeClass('hide'); + } - TreeView.prototype.initKeyNav = function() { - var li, liSelected; - li = $("tr.tree-item"); - liSelected = null; - return $('body').keydown(function(e) { - var next, path; - if ($("input:focus").length > 0 && (e.which === 38 || e.which === 40)) { - return false; + TreeView.prototype.initKeyNav = function() { + var li, liSelected; + li = $("tr.tree-item"); + liSelected = null; + return $('body').keydown(function(e) { + var next, path; + if ($("input:focus").length > 0 && (e.which === 38 || e.which === 40)) { + return false; + } + if (e.which === 40) { + if (liSelected) { + next = liSelected.next(); + if (next.length > 0) { + liSelected.removeClass("selected"); + liSelected = next.addClass("selected"); + } + } else { + liSelected = li.eq(0).addClass("selected"); } - if (e.which === 40) { - if (liSelected) { - next = liSelected.next(); - if (next.length > 0) { - liSelected.removeClass("selected"); - liSelected = next.addClass("selected"); - } - } else { - liSelected = li.eq(0).addClass("selected"); - } - return $(liSelected).focus(); - } else if (e.which === 38) { - if (liSelected) { - next = liSelected.prev(); - if (next.length > 0) { - liSelected.removeClass("selected"); - liSelected = next.addClass("selected"); - } - } else { - liSelected = li.last().addClass("selected"); - } - return $(liSelected).focus(); - } else if (e.which === 13) { - path = $('.tree-item.selected .tree-item-file-name a').attr('href'); - if (path) { - return gl.utils.visitUrl(path); + return $(liSelected).focus(); + } else if (e.which === 38) { + if (liSelected) { + next = liSelected.prev(); + if (next.length > 0) { + liSelected.removeClass("selected"); + liSelected = next.addClass("selected"); } + } else { + liSelected = li.last().addClass("selected"); } - }); - }; + return $(liSelected).focus(); + } else if (e.which === 13) { + path = $('.tree-item.selected .tree-item-file-name a').attr('href'); + if (path) { + return gl.utils.visitUrl(path); + } + } + }); + }; - return TreeView; - })(); -}).call(window); + return TreeView; +})(); diff --git a/app/assets/javascripts/user.js b/app/assets/javascripts/user.js index 19c9efe7fbd..3ab9ef5408e 100644 --- a/app/assets/javascripts/user.js +++ b/app/assets/javascripts/user.js @@ -2,34 +2,35 @@ import Cookies from 'js-cookie'; -((global) => { - global.User = class { - constructor({ action }) { - this.action = action; - this.placeProfileAvatarsToTop(); - this.initTabs(); - this.hideProjectLimitMessage(); - } +class User { + constructor({ action }) { + this.action = action; + this.placeProfileAvatarsToTop(); + this.initTabs(); + this.hideProjectLimitMessage(); + } - placeProfileAvatarsToTop() { - $('.profile-groups-avatars').tooltip({ - placement: 'top' - }); - } + placeProfileAvatarsToTop() { + $('.profile-groups-avatars').tooltip({ + placement: 'top' + }); + } - initTabs() { - return new global.UserTabs({ - parentEl: '.user-profile', - action: this.action - }); - } + initTabs() { + return new window.gl.UserTabs({ + parentEl: '.user-profile', + action: this.action + }); + } - hideProjectLimitMessage() { - $('.hide-project-limit-message').on('click', e => { - e.preventDefault(); - Cookies.set('hide_project_limit_message', 'false'); - $(this).parents('.project-limit-message').remove(); - }); - } - }; -})(window.gl || (window.gl = {})); + hideProjectLimitMessage() { + $('.hide-project-limit-message').on('click', e => { + e.preventDefault(); + Cookies.set('hide_project_limit_message', 'false'); + $(this).parents('.project-limit-message').remove(); + }); + } +} + +window.gl = window.gl || {}; +window.gl.User = User; diff --git a/app/assets/javascripts/user_tabs.js b/app/assets/javascripts/user_tabs.js index ce7eb76dc71..be70f4cb4e2 100644 --- a/app/assets/javascripts/user_tabs.js +++ b/app/assets/javascripts/user_tabs.js @@ -59,117 +59,118 @@ content on the Users#show page. */ -((global) => { - class UserTabs { - constructor ({ defaultAction, action, parentEl }) { - this.loaded = {}; - this.defaultAction = defaultAction || 'activity'; - this.action = action || this.defaultAction; - this.$parentEl = $(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() { - this.changeProjectsPageWrapper = this.changeProjectsPage.bind(this); - - 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)); - - this.$parentEl.on('click', '.gl-pagination a', this.changeProjectsPageWrapper); - } - - changeProjectsPage(e) { - e.preventDefault(); - - $('.tab-pane.active').empty(); - const endpoint = $(e.target).attr('href'); - this.loadTab(this.getCurrentAction(), endpoint); - } - - tabShown(event) { - const $target = $(event.target); - const action = $target.data('action'); - const source = $target.attr('href'); - const endpoint = $target.data('endpoint'); - this.setTab(action, endpoint); - return this.setCurrentAction(source); - } - - activateTab(action) { - return this.$parentEl.find(`.nav-links .js-${action}-tab a`) - .tab('show'); - } - - setTab(action, endpoint) { - if (this.loaded[action]) { - return; - } - if (action === 'activity') { - this.loadActivities(); - } - - const loadableActions = ['groups', 'contributed', 'projects', 'snippets']; - if (loadableActions.indexOf(action) > -1) { - return this.loadTab(action, endpoint); - } - } - - loadTab(action, endpoint) { - return $.ajax({ - beforeSend: () => this.toggleLoading(true), - complete: () => this.toggleLoading(false), - dataType: 'json', - type: 'GET', - url: endpoint, - success: (data) => { - const tabSelector = `div#${action}`; - this.$parentEl.find(tabSelector).html(data.html); - this.loaded[action] = true; - return gl.utils.localTimeAgo($('.js-timeago', tabSelector)); - } +class UserTabs { + constructor ({ defaultAction, action, parentEl }) { + this.loaded = {}; + this.defaultAction = defaultAction || 'activity'; + this.action = action || this.defaultAction; + this.$parentEl = $(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; } - loadActivities() { - if (this.loaded['activity']) { - return; - } - const $calendarWrap = this.$parentEl.find('.user-calendar'); - $calendarWrap.load($calendarWrap.data('href')); - new gl.Activities(); - return this.loaded['activity'] = true; + this.activateTab(this.action); + } + + bindEvents() { + this.changeProjectsPageWrapper = this.changeProjectsPage.bind(this); + + 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)); + + this.$parentEl.on('click', '.gl-pagination a', this.changeProjectsPageWrapper); + } + + changeProjectsPage(e) { + e.preventDefault(); + + $('.tab-pane.active').empty(); + const endpoint = $(e.target).attr('href'); + this.loadTab(this.getCurrentAction(), endpoint); + } + + tabShown(event) { + const $target = $(event.target); + const action = $target.data('action'); + const source = $target.attr('href'); + const endpoint = $target.data('endpoint'); + this.setTab(action, endpoint); + return this.setCurrentAction(source); + } + + activateTab(action) { + return this.$parentEl.find(`.nav-links .js-${action}-tab a`) + .tab('show'); + } + + setTab(action, endpoint) { + if (this.loaded[action]) { + return; + } + if (action === 'activity') { + this.loadActivities(); } - toggleLoading(status) { - return this.$parentEl.find('.loading-status .loading') - .toggle(status); - } - - setCurrentAction(source) { - let new_state = source; - new_state = new_state.replace(/\/+$/, ''); - new_state += this._location.search + this._location.hash; - history.replaceState({ - url: new_state - }, document.title, new_state); - return new_state; - } - - getCurrentAction() { - return this.$parentEl.find('.nav-links .active a').data('action'); + const loadableActions = ['groups', 'contributed', 'projects', 'snippets']; + if (loadableActions.indexOf(action) > -1) { + return this.loadTab(action, endpoint); } } - global.UserTabs = UserTabs; -})(window.gl || (window.gl = {})); + + loadTab(action, endpoint) { + return $.ajax({ + beforeSend: () => this.toggleLoading(true), + complete: () => this.toggleLoading(false), + dataType: 'json', + type: 'GET', + url: endpoint, + 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() { + if (this.loaded['activity']) { + return; + } + const $calendarWrap = this.$parentEl.find('.user-calendar'); + $calendarWrap.load($calendarWrap.data('href')); + new gl.Activities(); + return this.loaded['activity'] = true; + } + + toggleLoading(status) { + return this.$parentEl.find('.loading-status .loading') + .toggle(status); + } + + setCurrentAction(source) { + let new_state = source; + new_state = new_state.replace(/\/+$/, ''); + new_state += this._location.search + this._location.hash; + history.replaceState({ + url: new_state + }, document.title, new_state); + return new_state; + } + + getCurrentAction() { + return this.$parentEl.find('.nav-links .active a').data('action'); + } +} + +window.gl = window.gl || {}; +window.gl.UserTabs = UserTabs; diff --git a/app/assets/javascripts/username_validator.js b/app/assets/javascripts/username_validator.js index 137cefa3b8e..abe6c30f4f3 100644 --- a/app/assets/javascripts/username_validator.js +++ b/app/assets/javascripts/username_validator.js @@ -1,135 +1,133 @@ /* eslint-disable comma-dangle, consistent-return, class-methods-use-this, arrow-parens, no-param-reassign, max-len */ -((global) => { - const debounceTimeoutDuration = 1000; - const invalidInputClass = 'gl-field-error-outline'; - const successInputClass = 'gl-field-success-outline'; - const unavailableMessageSelector = '.username .validation-error'; - const successMessageSelector = '.username .validation-success'; - const pendingMessageSelector = '.username .validation-pending'; - const invalidMessageSelector = '.username .gl-field-error'; +const debounceTimeoutDuration = 1000; +const invalidInputClass = 'gl-field-error-outline'; +const successInputClass = 'gl-field-success-outline'; +const unavailableMessageSelector = '.username .validation-error'; +const successMessageSelector = '.username .validation-success'; +const pendingMessageSelector = '.username .validation-pending'; +const invalidMessageSelector = '.username .gl-field-error'; - class UsernameValidator { - constructor() { - this.inputElement = $('#new_user_username'); - this.inputDomElement = this.inputElement.get(0); - this.state = { - available: false, - valid: false, - pending: false, - empty: true - }; +class UsernameValidator { + constructor() { + this.inputElement = $('#new_user_username'); + this.inputDomElement = this.inputElement.get(0); + this.state = { + available: false, + valid: false, + pending: false, + empty: true + }; - const debounceTimeout = _.debounce((username) => { - this.validateUsername(username); - }, debounceTimeoutDuration); + const debounceTimeout = _.debounce((username) => { + this.validateUsername(username); + }, debounceTimeoutDuration); - this.inputElement.on('keyup.username_check', () => { - const username = this.inputElement.val(); + this.inputElement.on('keyup.username_check', () => { + const username = this.inputElement.val(); - this.state.valid = this.inputDomElement.validity.valid; - this.state.empty = !username.length; + this.state.valid = this.inputDomElement.validity.valid; + this.state.empty = !username.length; - if (this.state.valid) { - return debounceTimeout(username); - } - - this.renderState(); - }); - - // Override generic field validation - this.inputElement.on('invalid', this.interceptInvalid.bind(this)); - } - - renderState() { - // Clear all state - this.clearFieldValidationState(); - - if (this.state.valid && this.state.available) { - return this.setSuccessState(); - } - - if (this.state.empty) { - return this.clearFieldValidationState(); - } - - if (this.state.pending) { - return this.setPendingState(); - } - - if (!this.state.available) { - return this.setUnavailableState(); - } - - if (!this.state.valid) { - return this.setInvalidState(); - } - } - - interceptInvalid(event) { - event.preventDefault(); - event.stopPropagation(); - } - - validateUsername(username) { if (this.state.valid) { - this.state.pending = true; - this.state.available = false; - this.renderState(); - return $.ajax({ - type: 'GET', - url: `${gon.relative_url_root}/users/${username}/exists`, - dataType: 'json', - success: (res) => this.setAvailabilityState(res.exists) - }); + return debounceTimeout(username); } - } - setAvailabilityState(usernameTaken) { - if (usernameTaken) { - this.state.valid = false; - this.state.available = false; - } else { - this.state.available = true; - } - this.state.pending = false; this.renderState(); + }); + + // Override generic field validation + this.inputElement.on('invalid', this.interceptInvalid.bind(this)); + } + + renderState() { + // Clear all state + this.clearFieldValidationState(); + + if (this.state.valid && this.state.available) { + return this.setSuccessState(); } - clearFieldValidationState() { - this.inputElement.siblings('p').hide(); - - this.inputElement.removeClass(invalidInputClass) - .removeClass(successInputClass); + if (this.state.empty) { + return this.clearFieldValidationState(); } - setUnavailableState() { - const $usernameUnavailableMessage = this.inputElement.siblings(unavailableMessageSelector); - this.inputElement.addClass(invalidInputClass).removeClass(successInputClass); - $usernameUnavailableMessage.show(); + if (this.state.pending) { + return this.setPendingState(); } - setSuccessState() { - const $usernameSuccessMessage = this.inputElement.siblings(successMessageSelector); - this.inputElement.addClass(successInputClass).removeClass(invalidInputClass); - $usernameSuccessMessage.show(); + if (!this.state.available) { + return this.setUnavailableState(); } - setPendingState() { - const $usernamePendingMessage = $(pendingMessageSelector); - if (this.state.pending) { - $usernamePendingMessage.show(); - } else { - $usernamePendingMessage.hide(); - } - } - - setInvalidState() { - const $inputErrorMessage = $(invalidMessageSelector); - this.inputElement.addClass(invalidInputClass).removeClass(successInputClass); - $inputErrorMessage.show(); + if (!this.state.valid) { + return this.setInvalidState(); } } - global.UsernameValidator = UsernameValidator; -})(window); + interceptInvalid(event) { + event.preventDefault(); + event.stopPropagation(); + } + + validateUsername(username) { + if (this.state.valid) { + this.state.pending = true; + this.state.available = false; + this.renderState(); + return $.ajax({ + type: 'GET', + url: `${gon.relative_url_root}/users/${username}/exists`, + dataType: 'json', + success: (res) => this.setAvailabilityState(res.exists) + }); + } + } + + setAvailabilityState(usernameTaken) { + if (usernameTaken) { + this.state.valid = false; + this.state.available = false; + } else { + this.state.available = true; + } + this.state.pending = false; + this.renderState(); + } + + clearFieldValidationState() { + this.inputElement.siblings('p').hide(); + + this.inputElement.removeClass(invalidInputClass) + .removeClass(successInputClass); + } + + setUnavailableState() { + const $usernameUnavailableMessage = this.inputElement.siblings(unavailableMessageSelector); + this.inputElement.addClass(invalidInputClass).removeClass(successInputClass); + $usernameUnavailableMessage.show(); + } + + setSuccessState() { + const $usernameSuccessMessage = this.inputElement.siblings(successMessageSelector); + this.inputElement.addClass(successInputClass).removeClass(invalidInputClass); + $usernameSuccessMessage.show(); + } + + setPendingState() { + const $usernamePendingMessage = $(pendingMessageSelector); + if (this.state.pending) { + $usernamePendingMessage.show(); + } else { + $usernamePendingMessage.hide(); + } + } + + setInvalidState() { + const $inputErrorMessage = $(invalidMessageSelector); + this.inputElement.addClass(invalidInputClass).removeClass(successInputClass); + $inputErrorMessage.show(); + } +} + +window.UsernameValidator = UsernameValidator; diff --git a/app/assets/javascripts/visibility_select.js b/app/assets/javascripts/visibility_select.js index f712d7ba930..b6bbbaa0936 100644 --- a/app/assets/javascripts/visibility_select.js +++ b/app/assets/javascripts/visibility_select.js @@ -1,27 +1,24 @@ -(() => { - const gl = window.gl || (window.gl = {}); +class VisibilitySelect { + constructor(container) { + if (!container) throw new Error('VisibilitySelect requires a container element as argument 1'); + this.container = container; + this.helpBlock = this.container.querySelector('.help-block'); + this.select = this.container.querySelector('select'); + } - class VisibilitySelect { - constructor(container) { - if (!container) throw new Error('VisibilitySelect requires a container element as argument 1'); - this.container = container; - this.helpBlock = this.container.querySelector('.help-block'); - this.select = this.container.querySelector('select'); - } - - init() { - if (this.select) { - this.updateHelpText(); - this.select.addEventListener('change', this.updateHelpText.bind(this)); - } else { - this.helpBlock.textContent = this.container.querySelector('.js-locked').dataset.helpBlock; - } - } - - updateHelpText() { - this.helpBlock.textContent = this.select.querySelector('option:checked').dataset.description; + init() { + if (this.select) { + this.updateHelpText(); + this.select.addEventListener('change', this.updateHelpText.bind(this)); + } else { + this.helpBlock.textContent = this.container.querySelector('.js-locked').dataset.helpBlock; } } - gl.VisibilitySelect = VisibilitySelect; -})(); + updateHelpText() { + this.helpBlock.textContent = this.select.querySelector('option:checked').dataset.description; + } +} + +window.gl = window.gl || {}; +window.gl.VisibilitySelect = VisibilitySelect; diff --git a/app/assets/javascripts/wikis.js b/app/assets/javascripts/wikis.js index 4194c1bc08d..03d183ebd84 100644 --- a/app/assets/javascripts/wikis.js +++ b/app/assets/javascripts/wikis.js @@ -4,66 +4,65 @@ import 'vendor/jquery.nicescroll'; import './breakpoints'; -((global) => { - class Wikis { - constructor() { - this.bp = Breakpoints.get(); - this.sidebarEl = document.querySelector('.js-wiki-sidebar'); - this.sidebarExpanded = false; - $(this.sidebarEl).niceScroll(); +class Wikis { + constructor() { + this.bp = Breakpoints.get(); + this.sidebarEl = document.querySelector('.js-wiki-sidebar'); + this.sidebarExpanded = false; + $(this.sidebarEl).niceScroll(); - const sidebarToggles = document.querySelectorAll('.js-sidebar-wiki-toggle'); - for (let i = 0; i < sidebarToggles.length; i += 1) { - sidebarToggles[i].addEventListener('click', e => this.handleToggleSidebar(e)); - } - - this.newWikiForm = document.querySelector('form.new-wiki-page'); - if (this.newWikiForm) { - this.newWikiForm.addEventListener('submit', e => this.handleNewWikiSubmit(e)); - } - - window.addEventListener('resize', () => this.renderSidebar()); - this.renderSidebar(); + const sidebarToggles = document.querySelectorAll('.js-sidebar-wiki-toggle'); + for (let i = 0; i < sidebarToggles.length; i += 1) { + sidebarToggles[i].addEventListener('click', e => this.handleToggleSidebar(e)); } - handleNewWikiSubmit(e) { - if (!this.newWikiForm) return; - - const slugInput = this.newWikiForm.querySelector('#new_wiki_path'); - const slug = gl.text.slugify(slugInput.value); - - if (slug.length > 0) { - const wikisPath = slugInput.getAttribute('data-wikis-path'); - window.location.href = `${wikisPath}/${slug}`; - e.preventDefault(); - } + this.newWikiForm = document.querySelector('form.new-wiki-page'); + if (this.newWikiForm) { + this.newWikiForm.addEventListener('submit', e => this.handleNewWikiSubmit(e)); } - handleToggleSidebar(e) { + window.addEventListener('resize', () => this.renderSidebar()); + this.renderSidebar(); + } + + handleNewWikiSubmit(e) { + if (!this.newWikiForm) return; + + const slugInput = this.newWikiForm.querySelector('#new_wiki_path'); + const slug = gl.text.slugify(slugInput.value); + + if (slug.length > 0) { + const wikisPath = slugInput.getAttribute('data-wikis-path'); + window.location.href = `${wikisPath}/${slug}`; e.preventDefault(); - this.sidebarExpanded = !this.sidebarExpanded; - this.renderSidebar(); - } - - sidebarCanCollapse() { - const bootstrapBreakpoint = this.bp.getBreakpointSize(); - return bootstrapBreakpoint === 'xs' || bootstrapBreakpoint === 'sm'; - } - - renderSidebar() { - if (!this.sidebarEl) return; - const { classList } = this.sidebarEl; - if (this.sidebarExpanded || !this.sidebarCanCollapse()) { - if (!classList.contains('right-sidebar-expanded')) { - classList.remove('right-sidebar-collapsed'); - classList.add('right-sidebar-expanded'); - } - } else if (classList.contains('right-sidebar-expanded')) { - classList.add('right-sidebar-collapsed'); - classList.remove('right-sidebar-expanded'); - } } } - global.Wikis = Wikis; -})(window.gl || (window.gl = {})); + handleToggleSidebar(e) { + e.preventDefault(); + this.sidebarExpanded = !this.sidebarExpanded; + this.renderSidebar(); + } + + sidebarCanCollapse() { + const bootstrapBreakpoint = this.bp.getBreakpointSize(); + return bootstrapBreakpoint === 'xs' || bootstrapBreakpoint === 'sm'; + } + + renderSidebar() { + if (!this.sidebarEl) return; + const { classList } = this.sidebarEl; + if (this.sidebarExpanded || !this.sidebarCanCollapse()) { + if (!classList.contains('right-sidebar-expanded')) { + classList.remove('right-sidebar-collapsed'); + classList.add('right-sidebar-expanded'); + } + } else if (classList.contains('right-sidebar-expanded')) { + classList.add('right-sidebar-collapsed'); + classList.remove('right-sidebar-expanded'); + } + } +} + +window.gl = window.gl || {}; +window.gl.Wikis = Wikis; diff --git a/app/assets/javascripts/zen_mode.js b/app/assets/javascripts/zen_mode.js index b7fe552dec2..08f80735e93 100644 --- a/app/assets/javascripts/zen_mode.js +++ b/app/assets/javascripts/zen_mode.js @@ -34,65 +34,64 @@ window.Dropzone = Dropzone; // **Cancelable** No // **Target** a.js-zen-leave // -(function() { - this.ZenMode = (function() { - function ZenMode() { - this.active_backdrop = null; - this.active_textarea = null; - $(document).on('click', '.js-zen-enter', function(e) { - e.preventDefault(); - return $(e.currentTarget).trigger('zen_mode:enter'); - }); - $(document).on('click', '.js-zen-leave', function(e) { - e.preventDefault(); - return $(e.currentTarget).trigger('zen_mode:leave'); - }); - $(document).on('zen_mode:enter', (function(_this) { - return function(e) { - return _this.enter($(e.target).closest('.md-area').find('.zen-backdrop')); - }; - })(this)); - $(document).on('zen_mode:leave', (function(_this) { - return function(e) { - return _this.exit(); - }; - })(this)); - $(document).on('keydown', function(e) { - // Esc - if (e.keyCode === 27) { - e.preventDefault(); - return $(document).trigger('zen_mode:leave'); - } - }); - } - ZenMode.prototype.enter = function(backdrop) { - Mousetrap.pause(); - this.active_backdrop = $(backdrop); - this.active_backdrop.addClass('fullscreen'); - this.active_textarea = this.active_backdrop.find('textarea'); - // Prevent a user-resized textarea from persisting to fullscreen - this.active_textarea.removeAttr('style'); - return this.active_textarea.focus(); - }; - - ZenMode.prototype.exit = function() { - if (this.active_textarea) { - Mousetrap.unpause(); - this.active_textarea.closest('.zen-backdrop').removeClass('fullscreen'); - this.scrollTo(this.active_textarea); - this.active_textarea = null; - this.active_backdrop = null; - return Dropzone.forElement('.div-dropzone').enable(); +window.ZenMode = (function() { + function ZenMode() { + this.active_backdrop = null; + this.active_textarea = null; + $(document).on('click', '.js-zen-enter', function(e) { + e.preventDefault(); + return $(e.currentTarget).trigger('zen_mode:enter'); + }); + $(document).on('click', '.js-zen-leave', function(e) { + e.preventDefault(); + return $(e.currentTarget).trigger('zen_mode:leave'); + }); + $(document).on('zen_mode:enter', (function(_this) { + return function(e) { + return _this.enter($(e.target).closest('.md-area').find('.zen-backdrop')); + }; + })(this)); + $(document).on('zen_mode:leave', (function(_this) { + return function(e) { + return _this.exit(); + }; + })(this)); + $(document).on('keydown', function(e) { + // Esc + if (e.keyCode === 27) { + e.preventDefault(); + return $(document).trigger('zen_mode:leave'); } - }; + }); + } - ZenMode.prototype.scrollTo = function(zen_area) { - return $.scrollTo(zen_area, 0, { - offset: -150 - }); - }; + ZenMode.prototype.enter = function(backdrop) { + Mousetrap.pause(); + this.active_backdrop = $(backdrop); + this.active_backdrop.addClass('fullscreen'); + this.active_textarea = this.active_backdrop.find('textarea'); + // Prevent a user-resized textarea from persisting to fullscreen + this.active_textarea.removeAttr('style'); + return this.active_textarea.focus(); + }; - return ZenMode; - })(); -}).call(window); + ZenMode.prototype.exit = function() { + if (this.active_textarea) { + Mousetrap.unpause(); + this.active_textarea.closest('.zen-backdrop').removeClass('fullscreen'); + this.scrollTo(this.active_textarea); + this.active_textarea = null; + this.active_backdrop = null; + return Dropzone.forElement('.div-dropzone').enable(); + } + }; + + ZenMode.prototype.scrollTo = function(zen_area) { + return $.scrollTo(zen_area, 0, { + offset: -150 + }); + }; + + return ZenMode; +})();