diff options
author | Sam Rose <sam@gitlab.com> | 2017-04-18 17:42:53 -0400 |
---|---|---|
committer | Sam Rose <sam@gitlab.com> | 2017-05-09 13:42:15 -0400 |
commit | f11b6d598c6ece376ff207b9a3d321c3de29c668 (patch) | |
tree | 8ee15bf61c75f49fb52bdb39c3577cf9c391a5e9 | |
parent | 3f07aacb9cafac5a862766621dfaa67c48963d65 (diff) | |
download | gitlab-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.js | 7 | ||||
-rw-r--r-- | app/assets/javascripts/gl_lightbox.js | 133 | ||||
-rw-r--r-- | app/assets/javascripts/issue.js | 1 | ||||
-rw-r--r-- | app/assets/javascripts/merge_request.js | 1 | ||||
-rw-r--r-- | app/assets/javascripts/notes.js | 1 | ||||
-rw-r--r-- | app/assets/stylesheets/framework/lightbox.scss | 51 | ||||
-rw-r--r-- | lib/banzai/filter/image_link_filter.rb | 6 |
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 |