diff --git a/app/assets/javascripts/app/controllers/_click_catcher.js.coffee b/app/assets/javascripts/app/controllers/_click_catcher.js.coffee new file mode 100644 index 000000000..56378fa9a --- /dev/null +++ b/app/assets/javascripts/app/controllers/_click_catcher.js.coffee @@ -0,0 +1,20 @@ +class App.clickCatcher extends Spine.Controller + # clickCatcher has no template because it's a plain
+ className: 'clickCatcher' + + constructor: (holder, callback, zIndexScale) -> + super + @render() if @callback and @holder + + triggerCallback: (event) => + event.stopPropagation() + @callback() + @remove() + + render: -> + @el.addClass("zIndex-#{ @zIndexScale }") if @zIndexScale + @el.on('click', @triggerCallback) + @el.appendTo(@holder) + + remove: -> + @el.remove() \ No newline at end of file diff --git a/app/assets/javascripts/app/controllers/ticket_zoom.js.coffee b/app/assets/javascripts/app/controllers/ticket_zoom.js.coffee index 5686e02db..e1d209320 100644 --- a/app/assets/javascripts/app/controllers/ticket_zoom.js.coffee +++ b/app/assets/javascripts/app/controllers/ticket_zoom.js.coffee @@ -317,15 +317,18 @@ class Sidebar extends App.Controller class Edit extends App.Controller + elements: + 'textarea' : 'textarea' + events: 'click .submit': 'update' 'click [data-type="reset"]': 'reset' - 'click .visibility.toggle': 'toggle_visibility' + 'click .visibility-toggle': 'toggle_visibility' 'click .pop-selectable': 'select_type' 'click .pop-selected': 'show_selectable_types' 'focus textarea': 'show_controls' - 'blur textarea': 'hide_controls' - 'click .recipient-picker': 'toggle_recipients' + 'input textarea': 'detect_empty_textarea' + 'click .recipient-picker': 'show_recipients' 'click .recipient-list': 'stopPropagation' 'click .list-entry-type div': 'change_recipient_type' 'submit .recipient-list form': 'add_recipient' @@ -446,7 +449,7 @@ class Edit extends App.Controller # show text module UI if !@isRole('Customer') textModule = new App.WidgetTextModule( - el: @el.find('textarea') + el: @textarea data: ticket: ticket ) @@ -456,50 +459,58 @@ class Edit extends App.Controller ) @subscribeIdTextModule = ticket.subscribe( callback ) - toggle_recipients: => + show_recipients: => padding = 15 toggle = @el.find('.recipient-picker') list = @el.find('.recipient-list') arrow = list.find('.list-arrow') - if toggle.hasClass('state--open') - toggle.removeClass('state--open') - list.velocity - properties: - scale: [ 0, 1 ] - opacity: [ 0, 1 ] - options: - speed: 300 - easing: [ 500, 20 ] - complete: -> list.addClass('hide') - else - toggle.addClass('state--open') - list.removeClass('hide') + toggle.addClass('is-open') + list.removeClass('hide') - toggleDimensions = toggle.get(0).getBoundingClientRect() - availableHeight = toggle.scrollParent().outerHeight() + toggleDimensions = toggle.get(0).getBoundingClientRect() + availableHeight = toggle.scrollParent().outerHeight() - top = toggleDimensions.height/2 - list.height()/2 - bottomDistance = availableHeight - padding - (toggleDimensions.top + top + list.height()) + top = toggleDimensions.height/2 - list.height()/2 + bottomDistance = availableHeight - padding - (toggleDimensions.top + top + list.height()) - if bottomDistance < 0 - top += bottomDistance + if bottomDistance < 0 + top += bottomDistance - arrowCenter = -top + toggleDimensions.height/2 + arrowCenter = -top + toggleDimensions.height/2 - arrow.css('top', arrowCenter) - list.css('top', top) + arrow.css('top', arrowCenter) + list.css('top', top) - $.Velocity.hook(list, 'transformOriginX', "0") - $.Velocity.hook(list, 'transformOriginY', "#{ arrowCenter }px") + $.Velocity.hook(list, 'transformOriginX', "0") + $.Velocity.hook(list, 'transformOriginY', "#{ arrowCenter }px") - list.velocity - properties: - scale: [ 1, 0 ] - opacity: [ 1, 0 ] - options: - speed: 300 - easing: [ 0.34, 1.61, 0.7, 1 ] + list.velocity + properties: + scale: [ 1, 0 ] + opacity: [ 1, 0 ] + options: + speed: 300 + easing: [ 0.34, 1.61, 0.7, 1 ] + + @selectTypeCatcher = new App.clickCatcher + holder: @el.offsetParent() + callback: @hide_recipients + zIndexScale: 6 + + hide_recipients: => + list = @el.find('.recipient-list') + + @el.find('.recipient-picker').removeClass('is-open') + + list.velocity + properties: + scale: [ 0, 1 ] + opacity: [ 0, 1 ] + options: + speed: 300 + easing: [ 500, 20 ] + complete: -> list.addClass('hide') change_recipient_type: (e) -> $(e.target).addClass('active').siblings('.active').removeClass('active') @@ -512,18 +523,27 @@ class Edit extends App.Controller # store recipient toggle_visibility: -> - if @el.hasClass('state--public') - @el.removeClass('state--public') - @el.addClass('state--internal') + if @el.hasClass('is-public') + @el.removeClass('is-public') + @el.addClass('is-internal') else - @el.addClass('state--public') - @el.removeClass('state--internal') + @el.addClass('is-public') + @el.removeClass('is-internal') show_selectable_types: => @el.find('.pop-selector').removeClass('hide') + @selectTypeCatcher = new App.clickCatcher + holder: @el.offsetParent() + callback: @hide_type + zIndexScale: 6 + select_type: (e) => @set_type $(e.target).data('value') + @hide_type() + @selectTypeCatcher.remove() + + hide_type: => @el.find('.pop-selector').addClass('hide') set_type: (type) -> @@ -533,13 +553,33 @@ class Edit extends App.Controller @type = type typeIcon.addClass @type + detect_empty_textarea: => + if !@textarea.val() + @add_textarea_catcher() + else + @remove_textarea_catcher() + show_controls: => - @el.addClass('mode--edit') - # scroll to bottom - @el.scrollParent().scrollTop(99999) + if !@textareaCatcher and !@textarea.val() + @el.addClass('mode--edit') + # scroll to bottom + @el.scrollParent().scrollTop(99999) + @add_textarea_catcher() + + add_textarea_catcher: -> + @textareaCatcher = new App.clickCatcher + holder: @el.offsetParent() + callback: @hide_controls + zIndexScale: 4 + + remove_textarea_catcher: -> + return if !@textareaCatcher + @textareaCatcher.remove() + @textareaCatcher = null hide_controls: => - if !@el.find('textarea').val() + @remove_textarea_catcher() + if !@textarea.val() @el.removeClass('mode--edit') autosaveStop: => diff --git a/app/assets/javascripts/app/views/ticket_zoom.jst.eco b/app/assets/javascripts/app/views/ticket_zoom.jst.eco index a667cf1d6..d1c73c15e 100644 --- a/app/assets/javascripts/app/views/ticket_zoom.jst.eco +++ b/app/assets/javascripts/app/views/ticket_zoom.jst.eco @@ -1,7 +1,7 @@
-
+
-
-
+
<%- article.html %>
diff --git a/app/assets/javascripts/app/views/ticket_zoom/edit.jst.eco b/app/assets/javascripts/app/views/ticket_zoom/edit.jst.eco index 5934119c6..cc8148bf5 100644 --- a/app/assets/javascripts/app/views/ticket_zoom/edit.jst.eco +++ b/app/assets/javascripts/app/views/ticket_zoom/edit.jst.eco @@ -1,9 +1,9 @@
-
+
-
+
@@ -25,10 +25,12 @@

-
-
-
3
-
+
+
+
+
3
+
+
<%- @T('Recipients') %> @@ -42,7 +44,7 @@
Cc
- +
+
+
+
"> +
+
+
"> +
+
+
-
+
-
- Antwort eingeben oder +
+ Antwort eingeben oder Dateien wählen
-
-
-
-
-
-
internal
-
-
-
-
public
-
-
- -
-
\ No newline at end of file diff --git a/app/assets/stylesheets/zzz.css.erb b/app/assets/stylesheets/zzz.css.erb index 36005fcb9..f0aaa9871 100644 --- a/app/assets/stylesheets/zzz.css.erb +++ b/app/assets/stylesheets/zzz.css.erb @@ -19,11 +19,78 @@ small { } .u-clickable { + pointer-events: auto; cursor: pointer; -webkit-user-select: none; user-select: none; } +.u-positionOrigin { + position: relative; +} + +.zIndex-1, +.zIndex-2, +.zIndex-3, +.zIndex-4, +.zIndex-5, +.zIndex-6, +.zIndex-7, +.zIndex-8, +.zIndex-9, +.zIndex-10 { + position: relative; +} + +.zIndex-1 { + z-index: 100; +} +.zIndex-2 { + z-index: 200; +} +.zIndex-3 { + z-index: 300; +} +.zIndex-4 { + z-index: 400; +} +.zIndex-5 { + z-index: 500; +} +.zIndex-6 { + z-index: 600; +} +.zIndex-7 { + z-index: 700; +} +.zIndex-8 { + z-index: 800; +} +.zIndex-9 { + z-index: 900; +} +.zIndex-10 { + z-index: 1000; +} + +.clickCatcher { + bottom: 0; + left: 0; + width: 100%; + height: 100%; + position: absolute; + cursor: default; + background: rgba(255,255,0,.13); +} + +.clickCatcher + .clickCatcher { + background: rgba(255,0,255,.13); +} + +.clickCatcher + .clickCatcher + .clickCatcher { + background: rgba(0,255,128,.21); +} + #app > nav { position: relative; z-index: 1; @@ -34,7 +101,6 @@ a[data-tooltip], time[data-tooltip], span[data-tooltip] { position: relative; - z-index: 99000; } a[data-tooltip]:before, time[data-tooltip]:before, @@ -2495,6 +2561,11 @@ footer { transition: 500ms; } +.ticket-zoom .flex-overflow { + overflow: hidden; + min-height: 100%; +} + .ticket-zoom.state--sidebar-hidden .main { margin-right: 0; } @@ -2552,6 +2623,7 @@ footer { } .article-content { + position: relative; margin-right: 55px; } @@ -2565,10 +2637,6 @@ footer { position: absolute; width: 100%; } - .article-content { - position: relative; - z-index: 1; - } .article-meta { background: #2c2d36; @@ -2708,13 +2776,9 @@ footer { .ticket-edit { margin-top: auto; - margin-bottom: 37px; + margin-bottom: 36px; } - .ticket-edit.mode--edit { - margin-bottom: 8px; - } - .bottom-form { background: white; } @@ -2722,10 +2786,10 @@ footer { .ticket-edit .internal-border { padding: 5px; border-radius: 8px; - margin: -5px -5px 0; + margin: -5px; } - .ticket-edit.state--internal .internal-border { + .ticket-edit.is-internal .internal-border { background: repeating-linear-gradient(45deg, hsl(18,79%,89%), hsl(18,79%,89%) 5px, transparent 5px, transparent 6px); background-size: 8px 8px; } @@ -2762,53 +2826,45 @@ footer { margin: 0; } - .visibility.toggle { - margin-right: 10px; + .visibility-toggle { + height: 38px; + width: 38px; } - .visibility.toggle, + .visibility-toggle, .recipient-picker { opacity: 0.2; } - .visibility-label { - margin-left: 5px; - min-width: 53px; - line-height: 19px; - display: inline-block; - vertical-align: text-top; - } - - .state--public .internal-visibility { + .ticket-edit.is-public .internal-visibility { display: none; } - .state--internal .visibility.toggle { + .ticket-edit.is-internal .visibility-toggle { opacity: 1; } - .state--internal .public-visibility { + .ticket-edit.is-internal .public-visibility { display: none; } .ticket-edit .recipient-picker { - height: 38px; + height: 36px; position: relative; - z-index: 3; transition: 300ms; } - .ticket-edit .recipient-picker.state--open { + .ticket-edit .recipient-picker.is-open { opacity: 1; } .recipient-picker .icon { - margin-top: -8px; + margin-top: -3px; } .recipient-count { + margin-top: 5px; margin-left: 3px; - margin-top: 2px; line-height: 1; } @@ -2819,7 +2875,7 @@ footer { color: white; } - .recipient-picker.state--open .recipient-list { + .recipient-picker.is-open .recipient-list { display: block; } @@ -2924,7 +2980,7 @@ footer { } .ticket-edit.mode--edit textarea { - height: 115px; + height: 155px; } .ticket-edit.mode--edit .bubble-placeholder { @@ -2945,7 +3001,6 @@ footer { .pop-select { position: relative; - z-index: 2; } .pop-selector {