summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouwe Maan <douwe@selenight.nl>2017-04-13 12:05:09 -0500
committerDouwe Maan <douwe@selenight.nl>2017-04-27 12:23:26 -0500
commit796acbe1e05f934c02bc0ca9fca1747aab49267c (patch)
treecef0946254003e05392c82d8f4da6f63ac35e904
parent3079a2d63b54377c01ce5d09b96b3d7db20462aa (diff)
downloadgitlab-ce-796acbe1e05f934c02bc0ca9fca1747aab49267c.tar.gz
Add BlobViewer JS
-rw-r--r--app/assets/javascripts/blob/viewer/index.js130
-rw-r--r--app/assets/javascripts/dispatcher.js2
-rw-r--r--app/views/projects/blob/show.html.haml3
3 files changed, 135 insertions, 0 deletions
diff --git a/app/assets/javascripts/blob/viewer/index.js b/app/assets/javascripts/blob/viewer/index.js
new file mode 100644
index 00000000000..47c20d60446
--- /dev/null
+++ b/app/assets/javascripts/blob/viewer/index.js
@@ -0,0 +1,130 @@
+``/* eslint-disable no-new */
+/* global Flash */
+export default class BlobViewer {
+ constructor() {
+ this.switcherBtns = document.querySelectorAll('.js-blob-viewer-switcher');
+ this.copySourceBtn = document.querySelector('.js-copy-blob-source-btn');
+ this.simpleViewer = document.querySelector('.blob-viewer[data-type="simple"]');
+ this.richViewer = document.querySelector('.blob-viewer[data-type="rich"]');
+ this.$blobContentHolder = $('#blob-content-holder');
+
+ let initialViewerName = document.querySelector('.blob-viewer:not(.hidden)').getAttribute('data-type');
+
+ if (this.switcherBtns.length) {
+ this.initBindings();
+
+ if (location.hash.indexOf('#L') === 0) {
+ initialViewerName = 'simple';
+ }
+ }
+
+ this.switchToViewer(initialViewerName);
+ }
+
+ initBindings() {
+ Array.from(this.switcherBtns)
+ .forEach((el) => {
+ el.addEventListener('click', this.switchViewHandler.bind(this));
+ });
+
+ if (this.copySourceBtn) {
+ this.copySourceBtn.addEventListener('click', () => {
+ if (this.copySourceBtn.classList.contains('disabled')) return;
+
+ this.switchToViewer('simple');
+ });
+ }
+ }
+
+ switchViewHandler(e) {
+ const target = e.currentTarget;
+
+ e.preventDefault();
+
+ this.switchToViewer(target.getAttribute('data-viewer'));
+ }
+
+ toggleCopyButtonState() {
+ if (!this.copySourceBtn) return;
+
+ if (this.simpleViewer.getAttribute('data-loaded')) {
+ this.copySourceBtn.setAttribute('title', 'Copy source to clipboard');
+ this.copySourceBtn.classList.remove('disabled');
+ } else if (this.activeViewer == this.simpleViewer) {
+ this.copySourceBtn.setAttribute('title', 'Wait for the source to load to copy it to the clipboard');
+ this.copySourceBtn.classList.add('disabled');
+ } else {
+ this.copySourceBtn.setAttribute('title', 'Switch to the source to copy it to the clipboard');
+ this.copySourceBtn.classList.add('disabled');
+ }
+
+ $(this.copySourceBtn).tooltip('fixTitle');
+ }
+
+ loadViewer(viewerParam, resolve, reject) {
+ const viewer = viewerParam;
+ const url = viewer.getAttribute('data-url');
+
+ if (!url || viewer.getAttribute('data-loaded') || viewer.getAttribute('data-loading')) {
+ if (resolve) resolve();
+ return;
+ }
+
+ viewer.setAttribute('data-loading', 'true');
+
+ $.ajax({
+ url,
+ dataType: 'JSON',
+ })
+ .fail(() => {
+ if (reject) reject();
+ })
+ .done((data) => {
+ viewer.innerHTML = data.html;
+ $(viewer).syntaxHighlight();
+
+ viewer.setAttribute('data-loaded', 'true');
+
+ this.$blobContentHolder.trigger('highlight:line');
+
+ this.toggleCopyButtonState();
+
+ if (resolve) resolve();
+ });
+ }
+
+ switchToViewer(name) {
+ const newViewer = document.querySelector(`.blob-viewer[data-type='${name}']`);
+ if (this.activeViewer == newViewer) return;
+
+ const oldButton = document.querySelector('.js-blob-viewer-switcher.active')
+ const newButton = document.querySelector(`.js-blob-viewer-switcher[data-viewer='${name}']`);
+ const oldViewer = document.querySelector(`.blob-viewer:not([data-type='${name}'])`);
+
+ if (oldButton) {
+ oldButton.classList.remove('active');
+ }
+
+ if (newButton) {
+ newButton.classList.add('active');
+ newButton.blur();
+ }
+
+ if (oldViewer) {
+ oldViewer.classList.add('hidden');
+ }
+
+ newViewer.classList.remove('hidden');
+
+ this.activeViewer = newViewer;
+
+ this.toggleCopyButtonState();
+
+ return new Promise((resolve, reject) => {
+ this.loadViewer(newViewer, resolve, reject);
+ })
+ .catch(() => {
+ new Flash('Error loading file');
+ });
+ }
+}
diff --git a/app/assets/javascripts/dispatcher.js b/app/assets/javascripts/dispatcher.js
index b20673cd03c..d3d75c4bf4a 100644
--- a/app/assets/javascripts/dispatcher.js
+++ b/app/assets/javascripts/dispatcher.js
@@ -48,6 +48,7 @@ import BlobForkSuggestion from './blob/blob_fork_suggestion';
import UserCallout from './user_callout';
import { ProtectedTagCreate, ProtectedTagEditList } from './protected_tags';
import ShortcutsWiki from './shortcuts_wiki';
+import BlobViewer from './blob/viewer/index';
const ShortcutsBlob = require('./shortcuts_blob');
@@ -299,6 +300,7 @@ const ShortcutsBlob = require('./shortcuts_blob');
gl.TargetBranchDropDown.bootstrap();
break;
case 'projects:blob:show':
+ new BlobViewer();
gl.TargetBranchDropDown.bootstrap();
initBlob();
break;
diff --git a/app/views/projects/blob/show.html.haml b/app/views/projects/blob/show.html.haml
index b9b3f3ec7a3..67f57b5e4b9 100644
--- a/app/views/projects/blob/show.html.haml
+++ b/app/views/projects/blob/show.html.haml
@@ -2,6 +2,9 @@
- page_title @blob.path, @ref
= render "projects/commits/head"
+- content_for :page_specific_javascripts do
+ = page_specific_javascript_bundle_tag('blob')
+
%div{ class: container_class }
= render 'projects/last_push'