Commit 66dee188 authored by Douwe Maan's avatar Douwe Maan

Merge branch 'rs-zenmode-cleanup' into 'master'

Refactor ZenMode

- No longer depends on the "hidden checkbox".
- No longer depends on manually storing/restoring the scroll position.
  Instead, we take advantage of jquery.scrollTo.
- Event-based.
- Simplifies the state-based styling.

See merge request !2354
parents f41b535c 89ca4f04
# Zen Mode (full screen) textarea
#
#= provides zen_mode:enter
#= provides zen_mode:leave
#
#= require jquery.scrollTo
#= require dropzone #= require dropzone
#= require mousetrap #= require mousetrap
#= require mousetrap/pause #= require mousetrap/pause
#
# ### Events
#
# `zen_mode:enter`
#
# Fired when the "Edit in fullscreen" link is clicked.
#
# **Synchronicity** Sync
# **Bubbles** Yes
# **Cancelable** No
# **Target** a.js-zen-enter
#
# `zen_mode:leave`
#
# Fired when the "Leave Fullscreen" link is clicked.
#
# **Synchronicity** Sync
# **Bubbles** Yes
# **Cancelable** No
# **Target** a.js-zen-leave
#
class @ZenMode class @ZenMode
constructor: -> constructor: ->
@active_zen_area = null @active_backdrop = null
@active_checkbox = null @active_textarea = null
@scroll_position = 0
$(window).scroll =>
if not @active_checkbox
@scroll_position = window.pageYOffset
$('body').on 'click', '.zen-enter-link', (e) => $(document).on 'click', '.js-zen-enter', (e) ->
e.preventDefault() e.preventDefault()
$(e.currentTarget).closest('.zennable').find('.zen-toggle-comment').prop('checked', true).change() $(e.currentTarget).trigger('zen_mode:enter')
$('body').on 'click', '.zen-leave-link', (e) => $(document).on 'click', '.js-zen-leave', (e) ->
e.preventDefault() e.preventDefault()
$(e.currentTarget).closest('.zennable').find('.zen-toggle-comment').prop('checked', false).change() $(e.currentTarget).trigger('zen_mode:leave')
$('body').on 'change', '.zen-toggle-comment', (e) => $(document).on 'zen_mode:enter', (e) =>
checkbox = e.currentTarget @enter(e.target.parentNode)
if checkbox.checked $(document).on 'zen_mode:leave', (e) =>
# Disable other keyboard shortcuts in ZEN mode @exit()
Mousetrap.pause()
@updateActiveZenArea(checkbox) $(document).on 'keydown', (e) ->
else if e.keyCode == 27 # Esc
@exitZenMode()
$(document).on 'keydown', (e) =>
if e.keyCode is 27 # Esc
@exitZenMode()
e.preventDefault() e.preventDefault()
$(document).trigger('zen_mode:leave')
enter: (backdrop) ->
Mousetrap.pause()
@active_backdrop = $(backdrop)
@active_backdrop.addClass('fullscreen')
@active_textarea = @active_backdrop.find('textarea')
updateActiveZenArea: (checkbox) =>
@active_checkbox = $(checkbox)
@active_checkbox.prop('checked', true)
@active_zen_area = @active_checkbox.parent().find('textarea')
# Prevent a user-resized textarea from persisting to fullscreen # Prevent a user-resized textarea from persisting to fullscreen
@active_zen_area.removeAttr('style') @active_textarea.removeAttr('style')
@active_zen_area.focus() @active_textarea.focus()
exitZenMode: => exit: ->
if @active_zen_area isnt null if @active_textarea
Mousetrap.unpause() Mousetrap.unpause()
@active_checkbox.prop('checked', false)
@active_zen_area = null @active_textarea.closest('.zen-backdrop').removeClass('fullscreen')
@active_checkbox = null
@restoreScroll(@scroll_position) @scrollTo(@active_textarea)
# Enable dropzone when leaving ZEN mode
@active_textarea = null
@active_backdrop = null
Dropzone.forElement('.div-dropzone').enable() Dropzone.forElement('.div-dropzone').enable()
restoreScroll: (y) -> scrollTo: (zen_area) ->
window.scrollTo(window.pageXOffset, y) $.scrollTo(zen_area, 0, offset: -150)
.zennable { .zennable {
.zen-toggle-comment { a.js-zen-enter {
display: none;
}
.zen-enter-link {
color: $gl-gray; color: $gl-gray;
position: absolute; position: absolute;
top: 0px; top: 0px;
...@@ -11,7 +7,7 @@ ...@@ -11,7 +7,7 @@
line-height: 40px; line-height: 40px;
} }
.zen-leave-link { a.js-zen-leave {
display: none; display: none;
color: $gl-text-color; color: $gl-text-color;
position: absolute; position: absolute;
...@@ -25,62 +21,41 @@ ...@@ -25,62 +21,41 @@
} }
} }
// Hide the Enter link when we're in Zen mode .zen-backdrop {
input:checked ~ .zen-backdrop .zen-enter-link { &.fullscreen {
display: none; background-color: white;
} position: fixed;
top: 0;
// Show the Leave link when we're in Zen mode bottom: 0;
input:checked ~ .zen-backdrop .zen-leave-link { left: 0;
display: block; right: 0;
position: absolute; z-index: 1031;
top: 0;
} textarea {
border: none;
input:checked ~ .zen-backdrop { box-shadow: none;
background-color: white; border-radius: 0;
position: fixed; color: #000;
top: 0; font-size: 20px;
bottom: 0; line-height: 26px;
left: 0; padding: 30px;
right: 0; display: block;
z-index: 1031; outline: none;
resize: none;
textarea { height: 100vh;
border: none; max-width: 900px;
box-shadow: none; margin: 0 auto;
border-radius: 0; }
color: #000;
font-size: 20px; a.js-zen-enter {
line-height: 26px; display: none;
padding: 30px; }
display: block;
outline: none; a.js-zen-leave {
resize: none; display: block;
height: 100vh; position: absolute;
max-width: 900px; top: 0;
margin: 0 auto; }
} }
} }
// Make the color of the placeholder text in the Zenned-out textarea darker,
// so it becomes visible
input:checked ~ .zen-backdrop textarea::-webkit-input-placeholder {
color: #A8A8A8;
}
input:checked ~ .zen-backdrop textarea:-moz-placeholder {
color: #A8A8A8;
opacity: 1;
}
input:checked ~ .zen-backdrop textarea::-moz-placeholder {
color: #A8A8A8;
opacity: 1;
}
input:checked ~ .zen-backdrop textarea:-ms-input-placeholder {
color: #A8A8A8;
}
} }
.zennable .zennable
%input#zen-toggle-comment.zen-toggle-comment(tabindex="-1" type="checkbox")
.zen-backdrop .zen-backdrop
- classes << ' js-gfm-input markdown-area' - classes << ' js-gfm-input markdown-area'
- if defined?(f) && f - if defined?(f) && f
= f.text_area attr, class: classes, placeholder: '' = f.text_area attr, class: classes
- else - else
= text_area_tag attr, nil, class: classes, placeholder: '' = text_area_tag attr, nil, class: classes
%a.zen-enter-link(tabindex="-1" href="#") %a.js-zen-enter(tabindex="-1" href="#")
= icon('expand') = icon('expand')
Edit in fullscreen Edit in fullscreen
%a.zen-leave-link(href="#") %a.js-zen-leave(tabindex="-1" href="#")
= icon('compress') = icon('compress')
.zennable .zennable
%input#zen-toggle-comment.zen-toggle-comment{ tabindex: '-1', type: 'checkbox' }
.zen-backdrop .zen-backdrop
%textarea#note_note.js-gfm-input.markdown-area{placeholder: 'Leave a comment'} %textarea#note_note.js-gfm-input.markdown-area
%a.zen-enter-link{tabindex: '-1'} %a.js-zen-enter(tabindex="-1" href="#")
%i.fa.fa-expand %i.fa.fa-expand
Edit in fullscreen Edit in fullscreen
%a.zen-leave-link %a.js-zen-leave(tabindex="-1" href="#")
%i.fa.fa-compress %i.fa.fa-compress
...@@ -15,14 +15,6 @@ describe 'ZenMode', -> ...@@ -15,14 +15,6 @@ describe 'ZenMode', ->
# Set this manually because we can't actually scroll the window # Set this manually because we can't actually scroll the window
@zen.scroll_position = 456 @zen.scroll_position = 456
# Ohmmmmmmm
enterZen = ->
$('.zen-toggle-comment').prop('checked', true).trigger('change')
# Wh- what was that?!
exitZen = ->
$('.zen-toggle-comment').prop('checked', false).trigger('change')
describe 'on enter', -> describe 'on enter', ->
it 'pauses Mousetrap', -> it 'pauses Mousetrap', ->
spyOn(Mousetrap, 'pause') spyOn(Mousetrap, 'pause')
...@@ -35,16 +27,14 @@ describe 'ZenMode', -> ...@@ -35,16 +27,14 @@ describe 'ZenMode', ->
expect('textarea').not.toHaveAttr('style') expect('textarea').not.toHaveAttr('style')
describe 'in use', -> describe 'in use', ->
beforeEach -> beforeEach -> enterZen()
enterZen()
it 'exits on Escape', -> it 'exits on Escape', ->
$(document).trigger(jQuery.Event('keydown', {keyCode: 27})) escapeKeydown()
expect($('.zen-toggle-comment').prop('checked')).toBe(false) expect($('.zen-backdrop')).not.toHaveClass('fullscreen')
describe 'on exit', -> describe 'on exit', ->
beforeEach -> beforeEach -> enterZen()
enterZen()
it 'unpauses Mousetrap', -> it 'unpauses Mousetrap', ->
spyOn(Mousetrap, 'unpause') spyOn(Mousetrap, 'unpause')
...@@ -52,6 +42,10 @@ describe 'ZenMode', -> ...@@ -52,6 +42,10 @@ describe 'ZenMode', ->
expect(Mousetrap.unpause).toHaveBeenCalled() expect(Mousetrap.unpause).toHaveBeenCalled()
it 'restores the scroll position', -> it 'restores the scroll position', ->
spyOn(@zen, 'restoreScroll') spyOn(@zen, 'scrollTo')
exitZen() exitZen()
expect(@zen.restoreScroll).toHaveBeenCalledWith(456) expect(@zen.scrollTo).toHaveBeenCalled()
enterZen = -> $('a.js-zen-enter').click() # Ohmmmmmmm
exitZen = -> $('a.js-zen-leave').click()
escapeKeydown = -> $('textarea').trigger($.Event('keydown', {keyCode: 27}))
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment