summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSam Rose <sam@gitlab.com>2017-04-18 17:42:53 -0400
committerSam Rose <sam@gitlab.com>2017-05-09 13:42:15 -0400
commitf11b6d598c6ece376ff207b9a3d321c3de29c668 (patch)
tree8ee15bf61c75f49fb52bdb39c3577cf9c391a5e9
parent3f07aacb9cafac5a862766621dfaa67c48963d65 (diff)
downloadgitlab-ce-28387-lightbox-for-quick-image-zoom.tar.gz
Lightbox using Bootstrap modal28387-lightbox-for-quick-image-zoom
-rw-r--r--app/assets/javascripts/dispatcher.js7
-rw-r--r--app/assets/javascripts/gl_lightbox.js133
-rw-r--r--app/assets/javascripts/issue.js1
-rw-r--r--app/assets/javascripts/merge_request.js1
-rw-r--r--app/assets/javascripts/notes.js1
-rw-r--r--app/assets/stylesheets/framework/lightbox.scss51
-rw-r--r--lib/banzai/filter/image_link_filter.rb6
7 files changed, 92 insertions, 108 deletions
diff --git a/app/assets/javascripts/dispatcher.js b/app/assets/javascripts/dispatcher.js
index abb871c3af0..5a0f3598379 100644
--- a/app/assets/javascripts/dispatcher.js
+++ b/app/assets/javascripts/dispatcher.js
@@ -35,7 +35,7 @@
/* global ShortcutsWiki */
import Issue from './issue';
-
+import Lightbox from './gl_lightbox';
import BindInOut from './behaviors/bind_in_out';
import DeleteModal from './branches/branches_delete_modal';
import Group from './group';
@@ -132,6 +132,7 @@ const ShortcutsBlob = require('./shortcuts_blob');
new Issue();
shortcut_handler = new ShortcutsIssuable();
new ZenMode();
+ new Lightbox();
break;
case 'projects:milestones:show':
case 'groups:milestones:show':
@@ -187,6 +188,7 @@ const ShortcutsBlob = require('./shortcuts_blob');
shortcut_handler = new ShortcutsNavigation();
new gl.GLForm($('.issue-form'));
new IssuableForm($('.issue-form'));
+ new Lightbox();
new LabelsSelect();
new MilestoneSelect();
new gl.IssuableTemplateSelectors();
@@ -198,6 +200,7 @@ const ShortcutsBlob = require('./shortcuts_blob');
shortcut_handler = new ShortcutsNavigation();
new gl.GLForm($('.merge-request-form'));
new IssuableForm($('.merge-request-form'));
+ new Lightbox();
new LabelsSelect();
new MilestoneSelect();
new gl.IssuableTemplateSelectors();
@@ -215,10 +218,12 @@ const ShortcutsBlob = require('./shortcuts_blob');
new gl.Diff();
shortcut_handler = new ShortcutsIssuable(true);
new ZenMode();
+ new Lightbox();
break;
case "projects:merge_requests:diffs":
new gl.Diff();
new ZenMode();
+ new Lightbox();
break;
case 'dashboard:activity':
new gl.Activities();
diff --git a/app/assets/javascripts/gl_lightbox.js b/app/assets/javascripts/gl_lightbox.js
index 6dd6cfa1a0b..66bc2e14779 100644
--- a/app/assets/javascripts/gl_lightbox.js
+++ b/app/assets/javascripts/gl_lightbox.js
@@ -1,73 +1,82 @@
-/* eslint-disable no-new */
-/* jshint esversion: 6 */
-
-$(() => {
- const IMAGE_SELECTOR = '.no-attachment-icon';
-
- class GitLabLightbox {
- constructor() {
- this.$lightbox = null;
- this.$lbLink = null;
- this.$lbImage = null;
- this.$closeBtn = null;
- this.initLightbox();
- this.addBindings();
- }
-
- initLightbox() {
- /* Create base lightbox template
- <div class="gl-lightbox">
- <i class="fa fa-close dismiss"></i>
- <a href="#" target="_blank">
+export default class Lightbox {
+ constructor(selector) {
+ this.selector = selector || 'a.no-attachment-icon img';
+ this.modal = null;
+ this.modalDialog = null;
+ this.link = null;
+ this.image = null;
+ this.images = null;
+ this.buffer = 60;
+ this.bsMobile = 576;
+ this.maxWidth = 'none';
+ this.template = `
+ <div class="lb-modal modal fade"
+ tabindex="-1"
+ role="dialog"
+ aria-labelledby="">
+ <div class="modal-dialog">
+ <a href="" target="_blank" rel="noopener noreferrer">
<img src="" alt="" />
</a>
</div>
- */
- if (!document.querySelector('.gl-lightbox')) {
- this.$lightbox = $('<div/>', { class: 'gl-lightbox' });
- this.$closeBtn = $('<i/>', { class: 'fa fa-close dismiss' });
- this.$lbLink = $('<a/>', { href: '', target: '_blank' });
- this.$lbImage = $('<img/>', { src: '' });
- this.$lbLink.append(this.$lbImage);
- this.$lightbox.append(this.$closeBtn);
- this.$lightbox.append(this.$lbLink);
- $('body').append(this.$lightbox);
- }
- }
+ </div>
+ `;
- addBindings() {
- this.$lightbox.on('click', this.hideLightbox.bind(this));
- $(IMAGE_SELECTOR).on('click', this.showLightbox.bind(this));
- $(document).on('scroll', this.hideLightbox.bind(this));
- $(document).on('markdown-preview:fetched', this.addPreviewBindings.bind(this));
- $(document).on('ajax:success', '.gfm-form', this.addNoteBinding.bind(this));
- }
+ this.initModal();
+ this.bindImages();
+ this.watchEvents();
+ }
- addPreviewBindings(e, $form) {
- if (!$form) return;
- $form.find(IMAGE_SELECTOR).on('click', this.showLightbox.bind(this));
- }
+ initModal() {
+ this.modal = document.createElement('div');
+ this.modal.innerHTML = this.template;
+ this.modalDialog = this.modal.querySelector('.modal-dialog');
+ this.link = this.modal.querySelector('a');
+ this.image = this.modal.querySelector('img');
+ document.body.appendChild(this.modal);
+ }
- addNoteBinding(e, data) {
- $(`#note_${data.id} ${IMAGE_SELECTOR}`).on('click',
- this.showLightbox.bind(this));
- }
+ bindImages() {
+ this.images = document.querySelectorAll(this.selector);
+ this.images.forEach((image) => {
+ Object.assign(image.dataset, {
+ toggle: 'modal',
+ target: '.lb-modal',
+ });
+ image.addEventListener('click', this.clickHandler.bind(this));
+ });
+ }
- showLightbox(e) {
- e.preventDefault();
- this.$lightbox.addClass('show-box');
- this.$lbLink.attr('href', e.target.src);
- this.$lbImage.attr('src', e.target.src);
- this.$lbImage.attr('alt', e.target.alt);
- }
+ watchEvents() {
+ $(document).on('markdown-preview:fetched', this.addPreviewBindings.bind(this));
+ $(document).on('ajax:success', '.gfm-form', this.addNoteBinding.bind(this));
+ }
+
+ addPreviewBindings(e, $form) {
+ if (!$form) return;
+ const $img = $form.find(this.selector);
+ $img.attr('data-toggle', 'modal');
+ $img.attr('data-target', '.lb-modal');
+ $img.on('click', this.clickHandler.bind(this));
+ }
- hideLightbox() {
- this.$lightbox.removeClass('show-box');
- }
+ addNoteBinding(e, data) {
+ const $img = $(`#note_${data.id} ${this.selector}`);
+ $img.attr('data-toggle', 'modal');
+ $img.attr('data-target', '.lb-modal');
+ $img.on('click', this.clickHandler.bind(this));
}
- window.gl = window.gl || {};
- window.gl.GitLabLightbox = GitLabLightbox;
+ clickHandler(e) {
+ e.preventDefault();
+ this.maxWidth = Math.min(e.target.naturalWidth, window.innerWidth - this.buffer);
- new GitLabLightbox();
-});
+ this.maxWidth = window.innerWidth > this.bsMobile
+ ? this.maxWidth
+ : 'none';
+
+ this.link.setAttribute('href', e.target.src);
+ this.image.setAttribute('src', e.target.src);
+ this.modalDialog.style.maxWidth = `${this.maxWidth}px`;
+ }
+}
diff --git a/app/assets/javascripts/issue.js b/app/assets/javascripts/issue.js
index e948cc75dcc..694c6177a07 100644
--- a/app/assets/javascripts/issue.js
+++ b/app/assets/javascripts/issue.js
@@ -6,7 +6,6 @@ require('./flash');
require('~/lib/utils/text_utility');
require('vendor/jquery.waitforimages');
require('./task_list');
-require('./gl_lightbox');
class Issue {
constructor() {
diff --git a/app/assets/javascripts/merge_request.js b/app/assets/javascripts/merge_request.js
index e514c6ddac1..e9ea4616c91 100644
--- a/app/assets/javascripts/merge_request.js
+++ b/app/assets/javascripts/merge_request.js
@@ -19,7 +19,6 @@ require('./merge_request_tabs');
this.opts = opts != null ? opts : {};
this.submitNoteForm = bind(this.submitNoteForm, this);
this.$el = $('.merge-request');
- this.$lightbox = $('.lightbox');
this.$('.show-all-commits').on('click', (function(_this) {
return function() {
return _this.showAllCommits();
diff --git a/app/assets/javascripts/notes.js b/app/assets/javascripts/notes.js
index 02eec687f23..194c29f4710 100644
--- a/app/assets/javascripts/notes.js
+++ b/app/assets/javascripts/notes.js
@@ -16,7 +16,6 @@ require('./gfm_auto_complete');
require('vendor/jquery.caret'); // required by jquery.atwho
require('vendor/jquery.atwho');
require('./task_list');
-require('./gl_lightbox');
const normalizeNewlines = function(str) {
return str.replace(/\r\n/g, '\n');
diff --git a/app/assets/stylesheets/framework/lightbox.scss b/app/assets/stylesheets/framework/lightbox.scss
index 9c8b06a500c..851fbc4bbf7 100644
--- a/app/assets/stylesheets/framework/lightbox.scss
+++ b/app/assets/stylesheets/framework/lightbox.scss
@@ -1,46 +1,21 @@
-.gl-lightbox {
- position: fixed;
- top: -10vh;
- left: -100vw;
- height: 110vh;
- width: 100vw;
- display: flex;
- align-items: center;
- justify-content: center;
- background-color: $lightbox-bg;
- z-index: 100;
- opacity: 0;
- transition: opacity $lightbox-trans ease-in-out, top $lightbox-trans ease-in-out, left 0s linear $lightbox-trans;
-
- .dismiss {
- position: fixed;
- top: 15px;
- right: 15px;
- font-size: 18px;
- color: $gray-dark;
- cursor: pointer;
- opacity: 0;
- transition: opacity $lightbox-trans ease-in-out;
-
- &:hover {
- color: $white-normal;
- }
- }
-
+.no-attachment-icon img {
+ cursor: zoom-in;
+}
- &.show-box {
- top: -5vh;
- left: 0;
- opacity: 1;
- transition: opacity $lightbox-trans ease-in-out, top $lightbox-trans ease-in-out;
+.lb-modal {
+ .modal-dialog {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ overflow: hidden;
- .dismiss {
- opacity: 1;
+ @media (min-width: 576px) {
+ max-width: none;
}
}
img {
- max-width: 85vw;
- max-height: 85vh;
+ max-width: 100%;
+ margin: 0 auto;
}
}
diff --git a/lib/banzai/filter/image_link_filter.rb b/lib/banzai/filter/image_link_filter.rb
index 123c92fd250..ce23cf2add5 100644
--- a/lib/banzai/filter/image_link_filter.rb
+++ b/lib/banzai/filter/image_link_filter.rb
@@ -9,10 +9,8 @@ module Banzai
doc.xpath('descendant-or-self::img[not(ancestor::a)]').each do |img|
link = doc.document.create_element(
'a',
- class: 'no-attachment-icon',
- href: img['src'],
- target: '_blank',
- rel: 'noopener noreferrer'
+ href: '#',
+ class: 'no-attachment-icon'
)
link.children = img.clone