From 7679024a5d315389d86ad1d3ff17f29df9e770aa Mon Sep 17 00:00:00 2001 From: Felix Niklas Date: Tue, 9 Jun 2015 16:17:56 +0200 Subject: [PATCH] add clue animation --- .../app/controllers/layout_ref.js.coffee | 141 ++++++++++++++---- .../app/views/layout_ref/clue_content.jst.eco | 21 +++ .../app/views/layout_ref/clues.jst.eco | 33 +--- app/assets/stylesheets/zammad.css.scss | 22 +-- 4 files changed, 144 insertions(+), 73 deletions(-) create mode 100644 app/assets/javascripts/app/views/layout_ref/clue_content.jst.eco diff --git a/app/assets/javascripts/app/controllers/layout_ref.js.coffee b/app/assets/javascripts/app/controllers/layout_ref.js.coffee index 02f812ecc..960b89ae6 100644 --- a/app/assets/javascripts/app/controllers/layout_ref.js.coffee +++ b/app/assets/javascripts/app/controllers/layout_ref.js.coffee @@ -943,7 +943,7 @@ App.Config.set( 'layout_ref/highlight', highlightRef, 'Routes' ) class cluesRef extends App.ControllerContent - + clues: [ { container: '.search-holder' @@ -986,7 +986,12 @@ class cluesRef extends App.ControllerContent } ] + elements: + '.js-positionOrigin': 'modalWindow' + '.js-backdrop': 'backdrop' + events: + 'click': 'stopPropagation' 'click .js-next': 'next' 'click .js-previous': 'previous' 'click .js-close': 'close' @@ -1006,6 +1011,9 @@ class cluesRef extends App.ControllerContent @position = 0 @render() + stopPropagation: (event) -> + event.stopPropagation() + next: (event) => event.stopPropagation() @navigate 1 @@ -1017,28 +1025,43 @@ class cluesRef extends App.ControllerContent close: => @cleanUp() @options.onComplete() + @remove() - navigate: (direction) -> - @cleanUp() - @position += direction - - if @position < @clues.length - @render() - else - @options.onComplete() - - cleanUp: -> - clue = @clues[@position] - container = $(clue.container) - container.removeClass('selected-clue') - - # undo click perform by doing it again - if clue.actions - @perform clue.actions, container - + remove: -> @$('.modal').remove() + navigate: (direction) -> + @cleanUp => + @position += direction + + if @position < @clues.length + @showClue() + else + @options.onComplete() + @remove() + + cleanUp: (callback) -> + @hideWindow => + clue = @clues[@position] + container = $(clue.container) + container.removeClass('selected-clue') + + # undo click perform by doing it again + if clue.actions + @perform clue.actions, container + + callback() + render: -> + @html App.view('layout_ref/clues') + @backdrop.velocity + properties: + opacity: [1, 0] + options: + duration: 300 + complete: @showClue + + showClue: => clue = @clues[@position] container = $(clue.container) container.addClass('selected-clue') @@ -1054,20 +1077,47 @@ class cluesRef extends App.ControllerContent x: boundingBox.left + boundingBox.width/2 y: boundingBox.top + boundingBox.height/2 - @html App.view('layout_ref/clues') + @modalWindow.html App.view('layout_ref/clue_content') headline: clue.headline text: clue.text - width: boundingBox.width - height: boundingBox.height - center: center position: @position max: @clues.length @placeWindow(boundingBox) + @backdrop.velocity + properties: + translateX: center.x + translateY: center.y + translateZ: 0 + options: + duration: 300 + complete: @showWindow + + showWindow: => + @modalWindow.velocity + properties: + scale: [1, 0.2] + opacity: [1, 0] + options: + duration: 300 + easing: [0.34,1.61,0.7,1] + + hideWindow: (callback) => + @modalWindow.velocity + properties: + scale: [0.2, 1] + opacity: 0 + options: + duration: 200 + complete: callback + + placeWindow: (target) -> - modalElement = @$('.js-positionOrigin') - modal = modalElement.get(0).getBoundingClientRect() + # reset scale in order to get correct measurements + $.Velocity.hook(@modalWindow, 'scale', 1) + + modal = @modalWindow.get(0).getBoundingClientRect() position = '' left = 0 top = 0 @@ -1117,16 +1167,43 @@ class cluesRef extends App.ControllerContent moveArrow = modal.height/2 + maxHeight - (top + modal.height) top = maxHeight - modal.height - # show window - modalElement - .addClass "is-visible is-#{ position }" - .css - 'left': left - 'top': top + transformOrigin = @getTransformOrigin(modal, position) if moveArrow parameter = if position is 'above' or position is 'below' then 'left' else 'top' - modalElement.find('.js-arrow').css(parameter, moveArrow) + # move arrow + @modalWindow.find('.js-arrow').css(parameter, moveArrow) + + # adjust transform origin + if position is 'above' or position is 'below' + transformOrigin.x = moveArrow + else + transformOrigin.y = moveArrow + + # place window + @modalWindow + .attr 'data-position', position + .css + left: left + top: top + transformOrigin: "#{transformOrigin.x}px #{transformOrigin.y}px" + + getTransformOrigin: (modal, position) -> + positionDictionary = + above: + x: modal.width/2 + y: modal.height + @transformOriginPadding + below: + x: modal.width/2 + y: -@transformOriginPadding + left: + x: modal.width + @transformOriginPadding + y: modal.height/2 + right: + x: -@transformOriginPadding + y: modal.height/2 + + return positionDictionary[position] getVisibleBoundingBox: (el) -> ### diff --git a/app/assets/javascripts/app/views/layout_ref/clue_content.jst.eco b/app/assets/javascripts/app/views/layout_ref/clue_content.jst.eco new file mode 100644 index 000000000..9fc2c75f7 --- /dev/null +++ b/app/assets/javascripts/app/views/layout_ref/clue_content.jst.eco @@ -0,0 +1,21 @@ + \ No newline at end of file diff --git a/app/assets/javascripts/app/views/layout_ref/clues.jst.eco b/app/assets/javascripts/app/views/layout_ref/clues.jst.eco index 762f48574..cb5a7105f 100644 --- a/app/assets/javascripts/app/views/layout_ref/clues.jst.eco +++ b/app/assets/javascripts/app/views/layout_ref/clues.jst.eco @@ -1,33 +1,4 @@ \ No newline at end of file diff --git a/app/assets/stylesheets/zammad.css.scss b/app/assets/stylesheets/zammad.css.scss index 8c3ffc770..36ee56004 100644 --- a/app/assets/stylesheets/zammad.css.scss +++ b/app/assets/stylesheets/zammad.css.scss @@ -930,16 +930,17 @@ textarea, .modal-backdrop { bottom: 0; + width: 200%; + height: 200%; + left: -100%; + top: -100%; + background: radial-gradient(hsla(202,68%,54%,0.1), hsla(202,68%,54%,.9)); } .modal-spacer { position: absolute; opacity: 0; padding: 18px; - - &.is-visible { - opacity: 1; - } } .modal-arrow { @@ -953,18 +954,18 @@ textarea, transform: rotate(45deg); } - .modal-spacer.is-above .modal-arrow { + .modal-spacer[data-position="above"] .modal-arrow { left: 50%; top: 100%; background: hsl(210,5%,97%); } - .modal-spacer.is-below .modal-arrow { + .modal-spacer[data-position="below"] .modal-arrow { left: 50%; top: 0; } - .modal-spacer.is-left .modal-arrow { + .modal-spacer[data-position="left"] .modal-arrow { left: 100%; top: 50%; } @@ -1007,10 +1008,11 @@ textarea, } kbd { - background: hsl(200,8%,21%); + background: hsl(200,8%,90%); border-radius: 3px; - box-shadow: 0 1px 1px black; - color: white; + border: 1px solid hsl(240,7%,77%); + box-shadow: 0 1px rgba(0,0,0,.08); + color: hsl(240,7%,37%); display: inline-block; font-size: 12px; margin: 0 1px;