attachment + animation
This commit is contained in:
parent
47d450181c
commit
f7b4ac30ad
4 changed files with 135 additions and 99 deletions
|
@ -319,7 +319,14 @@ class Sidebar extends App.Controller
|
||||||
class Edit extends App.Controller
|
class Edit extends App.Controller
|
||||||
elements:
|
elements:
|
||||||
'textarea' : 'textarea'
|
'textarea' : 'textarea'
|
||||||
'.js-edit-control' : 'editControls'
|
'.edit-control-item' : 'editControlItem'
|
||||||
|
'.edit-controls': 'editControls'
|
||||||
|
'.recipient-picker': 'recipientPicker'
|
||||||
|
'.recipient-list': 'recipientList'
|
||||||
|
'.recipient-list .list-arrow': 'recipientListArrow'
|
||||||
|
'.js-attachment': 'attachmentHolder'
|
||||||
|
'.js-attachment-text': 'attachmentText'
|
||||||
|
'.bubble-placeholder-hint': 'bubblePlaceholderHint'
|
||||||
|
|
||||||
events:
|
events:
|
||||||
'click .submit': 'update'
|
'click .submit': 'update'
|
||||||
|
@ -329,9 +336,9 @@ class Edit extends App.Controller
|
||||||
'click .pop-selected': 'show_selectable_types'
|
'click .pop-selected': 'show_selectable_types'
|
||||||
'focus textarea': 'open_textarea'
|
'focus textarea': 'open_textarea'
|
||||||
'input textarea': 'detect_empty_textarea'
|
'input textarea': 'detect_empty_textarea'
|
||||||
'click .recipient-picker': 'show_recipients'
|
'click .recipient-picker': 'toggle_recipients'
|
||||||
'click .recipient-list': 'stopPropagation'
|
'click .recipient-list': 'stopPropagation'
|
||||||
'click .list-entry-type div': 'change_recipient_type'
|
'click .list-entry-type div': 'change_type'
|
||||||
'submit .recipient-list form': 'add_recipient'
|
'submit .recipient-list form': 'add_recipient'
|
||||||
|
|
||||||
constructor: ->
|
constructor: ->
|
||||||
|
@ -465,33 +472,36 @@ class Edit extends App.Controller
|
||||||
)
|
)
|
||||||
@subscribeIdTextModule = ticket.subscribe( callback )
|
@subscribeIdTextModule = ticket.subscribe( callback )
|
||||||
|
|
||||||
show_recipients: =>
|
toggle_recipients: =>
|
||||||
|
if !@pickRecipientsCatcher
|
||||||
|
@show_recipients()
|
||||||
|
else
|
||||||
|
@hide_recipients()
|
||||||
|
|
||||||
|
show_recipients: ->
|
||||||
padding = 15
|
padding = 15
|
||||||
toggle = @el.find('.recipient-picker')
|
|
||||||
list = @el.find('.recipient-list')
|
|
||||||
arrow = list.find('.list-arrow')
|
|
||||||
|
|
||||||
toggle.addClass('is-open')
|
@recipientPicker.addClass('is-open')
|
||||||
list.removeClass('hide')
|
@recipientList.removeClass('hide')
|
||||||
|
|
||||||
toggleDimensions = toggle.get(0).getBoundingClientRect()
|
pickerDimensions = @recipientPicker.get(0).getBoundingClientRect()
|
||||||
availableHeight = toggle.scrollParent().outerHeight()
|
availableHeight = @recipientPicker.scrollParent().outerHeight()
|
||||||
|
|
||||||
top = toggleDimensions.height/2 - list.height()/2
|
top = pickerDimensions.height/2 - @recipientList.height()/2
|
||||||
bottomDistance = availableHeight - padding - (toggleDimensions.top + top + list.height())
|
bottomDistance = availableHeight - padding - (pickerDimensions.top + top + @recipientList.height())
|
||||||
|
|
||||||
if bottomDistance < 0
|
if bottomDistance < 0
|
||||||
top += bottomDistance
|
top += bottomDistance
|
||||||
|
|
||||||
arrowCenter = -top + toggleDimensions.height/2
|
arrowCenter = -top + pickerDimensions.height/2
|
||||||
|
|
||||||
arrow.css('top', arrowCenter)
|
@recipientListArrow.css('top', arrowCenter)
|
||||||
list.css('top', top)
|
@recipientList.css('top', top)
|
||||||
|
|
||||||
$.Velocity.hook(list, 'transformOriginX', "0")
|
$.Velocity.hook(@recipientList, 'transformOriginX', "0")
|
||||||
$.Velocity.hook(list, 'transformOriginY', "#{ arrowCenter }px")
|
$.Velocity.hook(@recipientList, 'transformOriginY', "#{ arrowCenter }px")
|
||||||
|
|
||||||
list.velocity
|
@recipientList.velocity
|
||||||
properties:
|
properties:
|
||||||
scale: [ 1, 0 ]
|
scale: [ 1, 0 ]
|
||||||
opacity: [ 1, 0 ]
|
opacity: [ 1, 0 ]
|
||||||
|
@ -499,26 +509,27 @@ class Edit extends App.Controller
|
||||||
speed: 300
|
speed: 300
|
||||||
easing: [ 0.34, 1.61, 0.7, 1 ]
|
easing: [ 0.34, 1.61, 0.7, 1 ]
|
||||||
|
|
||||||
@selectTypeCatcher = new App.clickCatcher
|
@pickRecipientsCatcher = new App.clickCatcher
|
||||||
holder: @el.offsetParent()
|
holder: @el.offsetParent()
|
||||||
callback: @hide_recipients
|
callback: @hide_recipients
|
||||||
zIndexScale: 6
|
zIndexScale: 6
|
||||||
|
|
||||||
hide_recipients: =>
|
hide_recipients: =>
|
||||||
list = @el.find('.recipient-list')
|
@pickRecipientsCatcher.remove()
|
||||||
|
@pickRecipientsCatcher = null
|
||||||
|
|
||||||
@el.find('.recipient-picker').removeClass('is-open')
|
@recipientPicker.removeClass('is-open')
|
||||||
|
|
||||||
list.velocity
|
@recipientList.velocity
|
||||||
properties:
|
properties:
|
||||||
scale: [ 0, 1 ]
|
scale: [ 0, 1 ]
|
||||||
opacity: [ 0, 1 ]
|
opacity: [ 0, 1 ]
|
||||||
options:
|
options:
|
||||||
speed: 300
|
speed: 300
|
||||||
easing: [ 500, 20 ]
|
easing: [ 500, 20 ]
|
||||||
complete: -> list.addClass('hide')
|
complete: -> @recipientList.addClass('hide')
|
||||||
|
|
||||||
change_recipient_type: (e) ->
|
change_type: (e) ->
|
||||||
$(e.target).addClass('active').siblings('.active').removeClass('active')
|
$(e.target).addClass('active').siblings('.active').removeClass('active')
|
||||||
# store $(this).data('value')
|
# store $(this).data('value')
|
||||||
|
|
||||||
|
@ -548,6 +559,7 @@ class Edit extends App.Controller
|
||||||
@set_type $(e.target).data('value')
|
@set_type $(e.target).data('value')
|
||||||
@hide_type()
|
@hide_type()
|
||||||
@selectTypeCatcher.remove()
|
@selectTypeCatcher.remove()
|
||||||
|
@selectTypeCatcher = null
|
||||||
|
|
||||||
hide_type: =>
|
hide_type: =>
|
||||||
@el.find('.pop-selector').addClass('hide')
|
@el.find('.pop-selector').addClass('hide')
|
||||||
|
@ -567,35 +579,43 @@ class Edit extends App.Controller
|
||||||
|
|
||||||
open_textarea: =>
|
open_textarea: =>
|
||||||
if !@textareaCatcher and !@textarea.val()
|
if !@textareaCatcher and !@textarea.val()
|
||||||
@el.addClass('mode--edit')
|
@el.addClass('is-open')
|
||||||
|
|
||||||
|
@textarea.velocity
|
||||||
|
properties:
|
||||||
|
height: "#{ @textareaHeight.open - 38 }px"
|
||||||
|
marginBottom: 38
|
||||||
|
options:
|
||||||
|
duration: 300
|
||||||
|
easing: 'easeOutQuad'
|
||||||
|
|
||||||
# scroll to bottom
|
# scroll to bottom
|
||||||
@textarea.velocity "scroll",
|
@textarea.velocity "scroll",
|
||||||
container: @textarea.scrollParent()
|
container: @textarea.scrollParent()
|
||||||
offset: @textareaHeight.open - @textareaHeight.closed
|
offset: 99999
|
||||||
duration: 300
|
duration: 300
|
||||||
easing: 'easeOutQuad'
|
easing: 'easeOutQuad'
|
||||||
|
|
||||||
@textarea.velocity
|
|
||||||
properties:
|
|
||||||
height: "#{ @textareaHeight.open }px"
|
|
||||||
options:
|
|
||||||
speed: 300
|
|
||||||
easing: 'easeOutQuad'
|
|
||||||
queue: false
|
queue: false
|
||||||
|
|
||||||
@editControls.velocity
|
@editControlItem.velocity "transition.slideRightIn",
|
||||||
|
duration: 300
|
||||||
|
stagger: 50
|
||||||
|
drag: true
|
||||||
|
|
||||||
|
# move attachment text to the left bottom (bottom happens automatically)
|
||||||
|
|
||||||
|
@attachmentHolder.velocity
|
||||||
properties:
|
properties:
|
||||||
translateY: [
|
translateX: -@attachmentText.position().left + "px"
|
||||||
(i) -> (i+1) * 38,
|
|
||||||
'easeOutQuad',
|
|
||||||
0
|
|
||||||
]
|
|
||||||
opacity: [ 1, [ 0.34, 1.61, 0.7, 1 ], 0]
|
|
||||||
scale: [ 1, 'easeOutQuad', 0 ]
|
|
||||||
options:
|
options:
|
||||||
speed: 300
|
duration: 300
|
||||||
stagger: (i) -> i*100
|
easing: 'easeOutQuad'
|
||||||
|
|
||||||
|
@bubblePlaceholderHint.velocity
|
||||||
|
properties:
|
||||||
|
opacity: 0
|
||||||
|
options:
|
||||||
|
duration: 300
|
||||||
|
|
||||||
@add_textarea_catcher()
|
@add_textarea_catcher()
|
||||||
|
|
||||||
|
@ -613,28 +633,30 @@ class Edit extends App.Controller
|
||||||
close_textarea: =>
|
close_textarea: =>
|
||||||
@remove_textarea_catcher()
|
@remove_textarea_catcher()
|
||||||
if !@textarea.val()
|
if !@textarea.val()
|
||||||
@el.removeClass('mode--edit')
|
|
||||||
|
|
||||||
@textarea.velocity
|
@textarea.velocity
|
||||||
properties:
|
properties:
|
||||||
height: "#{ @textareaHeight.closed }px"
|
height: "#{ @textareaHeight.closed }px"
|
||||||
|
marginBottom: 0
|
||||||
options:
|
options:
|
||||||
speed: 300
|
duration: 300
|
||||||
|
easing: 'easeOutQuad'
|
||||||
|
complete: => @el.removeClass('is-open')
|
||||||
|
|
||||||
|
@attachmentHolder.velocity
|
||||||
|
properties:
|
||||||
|
translateX: 0
|
||||||
|
options:
|
||||||
|
duration: 300
|
||||||
easing: 'easeOutQuad'
|
easing: 'easeOutQuad'
|
||||||
|
|
||||||
@editControls.velocity
|
@bubblePlaceholderHint.velocity
|
||||||
properties:
|
properties:
|
||||||
translateY: [
|
opacity: 1
|
||||||
0,
|
|
||||||
'easeOutQuad',
|
|
||||||
(i) -> (i+1) * 38
|
|
||||||
]
|
|
||||||
scale: [ 0, [ 0.34, 1.61, 0.7, 1 ], 1 ]
|
|
||||||
opacity: [ 0, 'easeOutQuad', 1 ]
|
|
||||||
options:
|
options:
|
||||||
speed: 300
|
duration: 300
|
||||||
stagger: 300
|
|
||||||
backwards: true
|
@editControlItem.css('display', 'none')
|
||||||
|
|
||||||
autosaveStop: =>
|
autosaveStop: =>
|
||||||
@clearInterval( 'autosave' )
|
@clearInterval( 'autosave' )
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
<form class="ticket-update <% if @formChanged: %>form-changed<% end %>">
|
<form class="ticket-update <% if @formChanged: %>form-changed<% end %>">
|
||||||
<div class="bubble-grid horizontal">
|
<div class="bubble-grid horizontal">
|
||||||
<div class="vertical center u-positionOrigin">
|
<div class="vertical center edit-controls">
|
||||||
<div class="avatar user-popover zIndex-5" data-id="<%= @S('id') %>" style="background-image: url(<%- @S('image') %>)"></div>
|
<div class="avatar user-popover zIndex-5" data-id="<%= @S('id') %>" style="background-image: url(<%- @S('image') %>)"></div>
|
||||||
<div class="dark pop-select zIndex-7 js-edit-control">
|
<div class="dark pop-select zIndex-7 edit-control-item">
|
||||||
<div class="pop-selected u-clickable centered">
|
<div class="pop-selected u-clickable centered">
|
||||||
<div class="gray <%- @type %> channel icon"></div>
|
<div class="gray <%- @type %> channel icon"></div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -23,12 +23,12 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="u-positionOrigin js-edit-control">
|
<div class="u-positionOrigin zIndex-7 edit-control-item">
|
||||||
<div class="recipient-picker zIndex-5 u-clickable horizontal centered">
|
<div class="recipient-picker u-clickable horizontal centered">
|
||||||
<div class="recipients icon"></div>
|
<div class="recipients icon"></div>
|
||||||
<div class="recipient-count">3</div>
|
<div class="recipient-count">3</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="recipient-list zIndex-7 hide">
|
<div class="recipient-list hide">
|
||||||
<div class="list-arrow"></div>
|
<div class="list-arrow"></div>
|
||||||
<div class="list-head horizontal">
|
<div class="list-head horizontal">
|
||||||
<%- @T('Recipients') %>
|
<%- @T('Recipients') %>
|
||||||
|
@ -64,7 +64,7 @@
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="visibility-toggle zIndex-7 u-clickable js-edit-control">
|
<div class="visibility-toggle zIndex-7 u-clickable edit-control-item">
|
||||||
<div class="internal-visibility centered" title="<%- @T("unset internal") %>">
|
<div class="internal-visibility centered" title="<%- @T("unset internal") %>">
|
||||||
<div class="internal visibility icon"></div>
|
<div class="internal visibility icon"></div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -78,9 +78,13 @@
|
||||||
<div class="text-bubble">
|
<div class="text-bubble">
|
||||||
<div class="bubble-arrow"></div>
|
<div class="bubble-arrow"></div>
|
||||||
<textarea></textarea>
|
<textarea></textarea>
|
||||||
<div class="bubble-placeholder u-unclickable">
|
<!-- .text-bubble grows with textarea (and expanding clone) -->
|
||||||
Antwort eingeben oder
|
<div class="article-attachment js-attachment u-unclickable">
|
||||||
<span class="highlight u-clickable js-upload">Dateien wählen</span>
|
<span class="bubble-placeholder-hint">Antwort eingeben oder</span>
|
||||||
|
<span class="highlight u-clickable edit-upload-button js-attachment-text">
|
||||||
|
Dateien wählen..
|
||||||
|
<input multiple="multiple" type="file" name="file" style="position: absolute; right: 0px; top: 0px; font-family: Arial; font-size: 118px; margin: 0px; padding: 0px; cursor: pointer; opacity: 0;">
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
//= require ./app/lib/core/jquery-ui-1.8.23.custom.min.js
|
//= require ./app/lib/core/jquery-ui-1.8.23.custom.min.js
|
||||||
//= require ./app/lib/core/underscore-1.6.0.js
|
//= require ./app/lib/core/underscore-1.6.0.js
|
||||||
|
|
||||||
//= require ./app/lib/animations/jquery.velocity.min.js
|
//= require ./app/lib/animations/velocity.min.js
|
||||||
//= require ./app/lib/animations/velocity.ui.js
|
//= require ./app/lib/animations/velocity.ui.js
|
||||||
|
|
||||||
//not_used= require_tree ./app/lib/spine
|
//not_used= require_tree ./app/lib/spine
|
||||||
|
|
|
@ -80,15 +80,14 @@ small {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
cursor: default;
|
cursor: default;
|
||||||
background: rgba(255,255,0,.13);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.clickCatcher + .clickCatcher {
|
.debug .clickCatcher {
|
||||||
background: rgba(255,0,255,.13);
|
background: hsla(0,100%,50%,.13);
|
||||||
}
|
}
|
||||||
|
|
||||||
.clickCatcher + .clickCatcher + .clickCatcher {
|
.debug .clickCatcher + .clickCatcher {
|
||||||
background: rgba(0,255,128,.21);
|
background: hsla(50,100%,50%,.13);
|
||||||
}
|
}
|
||||||
|
|
||||||
#app > nav {
|
#app > nav {
|
||||||
|
@ -2798,32 +2797,39 @@ footer {
|
||||||
margin-bottom: 3px;
|
margin-bottom: 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ticket-edit .js-edit-control {
|
.edit-controls {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.edit-control-item {
|
||||||
width: 38px;
|
width: 38px;
|
||||||
height: 36px;
|
height: 36px;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 38px;
|
||||||
transform: scale(0);
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ticket-edit .js-edit-control:not(:last-child) {
|
.edit-control-item:nth-child(3) {
|
||||||
|
top: 74px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.edit-control-item:nth-child(4) {
|
||||||
|
top: 110px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.edit-control-item:not(:last-child) {
|
||||||
border-bottom: 1px solid #e6e6e6;
|
border-bottom: 1px solid #e6e6e6;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ticket-edit .pop-selectable .icon {
|
.pop-selectable .icon {
|
||||||
opacity: 0.3;
|
opacity: 0.3;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ticket-edit .pop-selectable:hover .icon {
|
.pop-selectable:hover .icon {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ticket-edit button[type=submit] {
|
|
||||||
margin: 5px 0;
|
|
||||||
float: right;
|
|
||||||
}
|
|
||||||
|
|
||||||
.visibility-toggle > * {
|
.visibility-toggle > * {
|
||||||
height: 36px;
|
height: 36px;
|
||||||
width: 38px;
|
width: 38px;
|
||||||
|
@ -2970,20 +2976,18 @@ footer {
|
||||||
border-color: #b3b3b3;
|
border-color: #b3b3b3;
|
||||||
white-space: normal;
|
white-space: normal;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ticket-edit textarea {
|
.ticket-edit textarea {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 38px;
|
height: 38px;
|
||||||
padding: 10px 20px;
|
padding: 10px;
|
||||||
vertical-align: bottom;
|
vertical-align: bottom;
|
||||||
border: none;
|
border: none;
|
||||||
background: none;
|
background: none;
|
||||||
outline: none;
|
outline: none;
|
||||||
}
|
resize: none;
|
||||||
|
|
||||||
.ticket-edit.mode--edit .bubble-placeholder {
|
|
||||||
opacity: 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.ticket-edit .bubble-arrow:after {
|
.ticket-edit .bubble-arrow:after {
|
||||||
|
@ -2991,22 +2995,28 @@ footer {
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.bubble-placeholder {
|
.article-attachment {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
left: 10px;
|
||||||
|
width: 100%;
|
||||||
|
height: 38px;
|
||||||
|
padding: 10px 0;
|
||||||
color: #b3b3b3;
|
color: #b3b3b3;
|
||||||
left: 20px;
|
|
||||||
top: 10px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.pop-select {
|
.edit-upload-button {
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
display: inline-block;
|
||||||
|
overflow: hidden;
|
||||||
|
vertical-align: bottom;
|
||||||
|
}
|
||||||
|
|
||||||
.pop-selector {
|
.pop-selector {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.pop-selected,
|
.pop-selected,
|
||||||
.pop-selectable {
|
.pop-selectable {
|
||||||
|
|
Loading…
Reference in a new issue