get started v1.1

This commit is contained in:
Felix Niklas 2015-06-08 11:16:08 +02:00
parent 9da504152a
commit 60e4308f5c
5 changed files with 255 additions and 129 deletions

View file

@ -938,21 +938,34 @@ class cluesRef extends App.ControllerContent
clues: [ clues: [
{ {
container: '.search' container: '.user-menu'
headline: 'Persönliches Menü'
text: 'Hier findest du den Logout, den Weg zu deinen Einstellungen und deinen Verlauf.'
actions: [
'click .user .js-action',
'hover .user'
]
}
{
container: '.search-holder'
headline: 'Suche' headline: 'Suche'
text: 'Hier finden sie alles!' text: 'Um alles zu finden nutze den <kbd>*</kbd>-Platzhalter'
}, },
{ {
container: '.user-menu' container: '.user-menu'
headline: 'Erstellen' headline: 'Erstellen'
text: 'Hier können sie Tickets, Kunden und Organisationen anlegen.' text: 'Hier kannst du Tickets, Kunden und Organisationen anlegen.'
action: 'click .add .js-action' actions: [
'click .add .js-action',
'hover .add'
]
} }
] ]
events: events:
'click .js-next': 'next' 'click .js-next': 'next'
'click .js-previous': 'previous' 'click .js-previous': 'previous'
'click .js-close': 'close'
constructor: -> constructor: ->
super super
@ -965,7 +978,7 @@ class cluesRef extends App.ControllerContent
### ###
@options.onComplete = -> @options.onComplete = -> null
@position = 0 @position = 0
@render() @render()
@ -977,6 +990,10 @@ class cluesRef extends App.ControllerContent
event.stopPropagation() event.stopPropagation()
@navigate -1 @navigate -1
close: =>
@cleanUp()
@options.onComplete()
navigate: (direction) -> navigate: (direction) ->
@cleanUp() @cleanUp()
@position += direction @position += direction
@ -984,7 +1001,7 @@ class cluesRef extends App.ControllerContent
if @position < @clues.length if @position < @clues.length
@render() @render()
else else
@onComplete() @options.onComplete()
cleanUp: -> cleanUp: ->
clue = @clues[@position] clue = @clues[@position]
@ -992,66 +1009,147 @@ class cluesRef extends App.ControllerContent
container.removeClass('selected-clue') container.removeClass('selected-clue')
# undo click perform by doing it again # undo click perform by doing it again
if clue.action if clue.actions
@perform clue.action, container @perform clue.actions, container
@el.find('.clue').remove() @$('.modal').remove()
render: -> render: ->
clue = @clues[@position] clue = @clues[@position]
container = $(clue.container) container = $(clue.container)
container.addClass('selected-clue') container.addClass('selected-clue')
if clue.actions
@perform clue.actions, container
# calculate bounding box after actions
# to take toggled child nodes into account
boundingBox = @getVisibleBoundingBox(container.get(0))
center = center =
x: container.offset().left + container.width()/2 x: boundingBox.left + boundingBox.width/2
y: container.offset().top + container.height()/2 y: boundingBox.top + boundingBox.height/2
@html App.view('layout_ref/clues') @html App.view('layout_ref/clues')
headline: clue.headline headline: clue.headline
text: clue.text text: clue.text
width: container.outerWidth() width: boundingBox.width
height: container.outerHeight() height: boundingBox.height
center: center center: center
position: @position position: @position
max: @clues.length max: @clues.length
if clue.action @placeWindow(boundingBox)
@perform clue.action, container
@placeWindow(container) placeWindow: (target) ->
modalElement = @$('.js-positionOrigin')
modal = modalElement.get(0).getBoundingClientRect()
position = ''
left = 0
top = 0
maxWidth = $(window).width()
maxHeight = $(window).height()
placeWindow: (container) -> # try to place it parallel to the larger side
clueWindow = @el.find('.clue-window') if target.height > target.width
# try to place it aside
# see if we can place it above or below target # prefer right
if clueWindow.outerHeight() + container.outerHeight() < $(window).outerHeight() if target.right + modal.width <= maxWidth
clueWindow.css('left', container.offset().left) left = target.right
position = 'right'
# below or above ?
if container.offset().top + container.outerHeight() + clueWindow.outerHeight() < $(window).outerHeight()
# place below
clueWindow.css('top', container.offset().top + container.outerHeight())
else
# place above
clueWindow.css('top', container.offset().top - container.outerHeight() - clueWindow.outerHeight())
else
clueWindow.css('top', container.offset().top)
# okay, let's try right or left then
if container.offset().left + container.outerWidth() + clueWindow.outerWidth() < $(window).outerWidth()
# place right
clueWindow.css('left', container.offset().left + container.outerWidth())
else else
# place left # place left
clueWindow.css('left', container.offset().left - container.outerWidth() - clueWindow.outerWidth()) left = target.left - modal.width
position = 'left'
if position
top = target.top + target.height/2 - modal.height/2
else if target.height <= target.width or !position
# try to place it above or below
# prefer above
if target.top - modal.height >= 0
top = target.top - modal.height
position = 'above'
else
top = target.bottom
position = 'below'
if position
left = target.left + target.width/2 - modal.width/2
# keep it inside the window
# horizontal
if left < 0
moveArrow = modal.width/2 + left
left = 0
else if left + modal.width > maxWidth
moveArrow = modal.width/2 + maxWidth - (left + modal.width)
left = maxWidth - modal.width
if top < 0
moveArrow = modal.height/2 + height
top = 0
else if top + modal.height > maxHeight
moveArrow = modal.height/2 + maxHeight - (top + modal.height)
top = maxHeight - modal.height
# show window # show window
clueWindow.addClass('is-visible') modalElement
.addClass "is-visible is-#{ position }"
.css
'left': left
'top': top
if moveArrow
parameter = if position is 'above' or position is 'below' then 'left' else 'top'
console.log("move arrow", position, parameter, moveArrow)
modalElement.find('.js-arrow').css(parameter, moveArrow)
perform: (action, container) -> getVisibleBoundingBox: (el) ->
eventName = action.substr 0, action.indexOf(' ') ###
selector = action.substr action.indexOf(' ') + 1
container.find(selector)[0][eventName]() getBoundingClientRect doesn't take
absolute-positioned child nodes into account
###
children = el.querySelectorAll('*')
bb = el.getBoundingClientRect()
dimensions =
left: bb.left,
right: bb.right,
top: bb.top,
bottom: bb.bottom
for child in children
continue if getComputedStyle(child).position is not 'absolute'
bb = child.getBoundingClientRect()
continue if bb.width is 0 or bb.height is 0
if bb.left < dimensions.left
dimensions.left = bb.left
if bb.top < dimensions.top
dimensions.top = bb.top
if bb.right > dimensions.right
dimensions.right = bb.right
if bb.bottom > dimensions.bottom
dimensions.bottom = bb.bottom
dimensions.width = dimensions.right - dimensions.left
dimensions.height = dimensions.bottom - dimensions.top
dimensions
perform: (actions, container) ->
for action in actions
eventName = action.substr 0, action.indexOf(' ')
selector = action.substr action.indexOf(' ') + 1
switch eventName
when 'click' then container.find(selector).trigger('click')
when 'hover' then container.find(selector).toggleClass('is-hovered')
App.Config.set( 'layout_ref/clues', cluesRef, 'Routes' ) App.Config.set( 'layout_ref/clues', cluesRef, 'Routes' )

View file

@ -1,22 +1,26 @@
<div class="clue"> <div class="modal modal--clue">
<div class="clue-backdrop" style="background: <div class="modal-backdrop" style="background:
radial-gradient( radial-gradient(
ellipse <%= @width + 400 %>px <%= @height + 400 %>px ellipse <%= @width + 400 %>px <%= @height + 400 %>px
at <%= @center.x %>px <%= @center.y %>px, at <%= @center.x %>px <%= @center.y %>px,
hsla(202,68%,54%,.4), hsla(202,68%,54%,.4),
hsla(202,68%,54%,.8) hsla(202,68%,54%,.9)
) )
"></div> "></div>
<div class="clue-window"> <div class="modal-spacer js-positionOrigin">
<div class="clue-inner"> <div class="modal-content">
<div class="clue-header"><%= @headline %></div> <div class="modal-arrow js-arrow"></div>
<div class="clue-body"><%= @text %></div> <div class="modal-close js-close">
<div class="clue-controls"> <svg class="icon-diagonal-cross"><use xlink:href="#icon-diagonal-cross" /></svg>
<div class="clue-control"> </div>
<div class="modal-header"><%= @headline %></div>
<div class="modal-body"><%- @text %></div>
<div class="modal-controls">
<div class="modal-control">
<div class="<% if @position is 0: %>is-disabled <% end %>btn btn--text js-previous"><%- @T( 'Previous' ) %></div> <div class="<% if @position is 0: %>is-disabled <% end %>btn btn--text js-previous"><%- @T( 'Previous' ) %></div>
</div> </div>
<div class="clue-control clue-count"><%= @position+1 %>/<%= @max %></div> <div class="modal-control clue-count"><%= @position+1 %>/<%= @max %></div>
<div class="clue-control"> <div class="modal-control">
<% if @position+1 is @max: %> <% if @position+1 is @max: %>
<div class="btn btn--text js-next"><%- @T( 'Finish' ) %></div> <div class="btn btn--text js-next"><%- @T( 'Finish' ) %></div>
<% else: %> <% else: %>

View file

@ -718,15 +718,6 @@ code {
background-color: #f9f2f4; background-color: #f9f2f4;
border-radius: 4px; border-radius: 4px;
} }
kbd {
padding: 2px 4px;
font-size: 90%;
color: #fff;
background-color: #333;
border-radius: 3px;
-webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .25);
box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .25);
}
kbd kbd { kbd kbd {
padding: 0; padding: 0;
font-size: 100%; font-size: 100%;

View file

@ -19,6 +19,7 @@ body {
background: hsl(210,17%,98%); background: hsl(210,17%,98%);
height: 100%; height: 100%;
color: hsl(198,19%,72%); color: hsl(198,19%,72%);
word-break: break-all;
} }
p { p {
@ -910,69 +911,100 @@ textarea,
@extend .zIndex-9; @extend .zIndex-9;
} }
.clue { .modal--clue {
position: fixed;
left: 0;
top: 0;
width: 100%;
height: 100%;
@extend .zIndex-8;
}
.clue-backdrop {
width: 100%;
height: 100%;
position: absolute;
left: 0;
top: 0;
}
.clue-window {
position: absolute;
opacity: 1;
padding: 18px;
&.is-visible {
opacity: 1;
}
}
.clue-inner {
min-width: 260px;
padding: 24px 24px 14px;
background: white;
color: hsl(60,1%,34%);
box-shadow:
0 8px 17px 0 rgba(0, 0, 0, 0.1),
0 6px 20px 0 rgba(0, 0, 0, 0.05);
}
.clue-controls {
background: hsl(210,5%,97%);
margin: 24px -24px -14px;
padding: 7px 10px;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between; justify-content: center;
} @extend .zIndex-8;
.clue-control { .modal-backdrop {
padding-left: 14px; bottom: 0;
padding-right: 14px; }
.btn.is-disabled { .modal-spacer {
opacity: 1; position: absolute;
color: hsl(240,5%,83%); opacity: 0;
padding: 18px;
&.is-visible {
opacity: 1;
}
}
.modal-arrow {
background: inherit;
width: 20px;
height: 20px;
position: absolute;
margin: -10px 0 53px -10px;
left: 0;
top: 50%;
transform: rotate(45deg);
}
.modal-spacer.is-above .modal-arrow {
left: 50%;
top: 100%;
background: hsl(210,5%,97%);
}
.modal-spacer.is-below .modal-arrow {
left: 50%;
top: 0;
}
.modal-spacer.is-left .modal-arrow {
left: 100%;
top: 50%;
}
.modal-content {
border: none;
width: 300px;
box-shadow:
0 8px 17px 0 rgba(0, 0, 0, 0.1),
0 6px 20px 0 rgba(0, 0, 0, 0.05);
}
.modal-controls {
background: hsl(210,5%,97%);
margin: 23px 0 0;
padding: 7px 10px;
display: flex;
align-items: center;
justify-content: space-between;
}
.modal-control {
padding-left: 14px;
padding-right: 14px;
.btn.is-disabled {
opacity: 1;
color: hsl(240,5%,83%);
}
}
.modal-header {
padding-bottom: 7px;
font-size: 18px;
}
.modal-body {
max-width: 340px;
} }
} }
.clue-header { kbd {
margin-bottom: 7px; background: hsl(200,8%,21%);
font-size: 18px; border-radius: 3px;
} box-shadow: 0 1px 1px black;
color: white;
.clue-body { display: inline-block;
max-width: 340px; font-size: 12px;
margin: 0 1px;
padding: 0 4px;
vertical-align: top;
} }
.form-stacked .checkbox label { .form-stacked .checkbox label {
@ -1828,7 +1860,7 @@ footer {
} }
.search { .search {
padding: 7px 5px 4px 10px; padding: 11px 5px 4px 10px;
border-bottom: 1px solid rgba(240, 250, 255, .05); border-bottom: 1px solid rgba(240, 250, 255, .05);
flex-shrink: 0; flex-shrink: 0;
display: flex; display: flex;
@ -1837,8 +1869,7 @@ footer {
.search-holder { .search-holder {
flex: 1; flex: 1;
margin-right: 2px; border-radius: 15px;
margin-top: 4px;
position: relative; position: relative;
transition: 240ms; transition: 240ms;
} }
@ -1900,7 +1931,7 @@ footer {
.search .logo { .search .logo {
position: relative; position: relative;
@extend .u-clickable, .zIndex-5; @extend .u-clickable, .zIndex-5;
margin: 0 10px; margin: -4px 10px 0 12px;
transition: 240ms; transition: 240ms;
} }
@ -1983,7 +2014,8 @@ footer {
position: relative; position: relative;
} }
.user-menu > li:hover .list-button:before { .user-menu > li:hover .list-button:before,
.user-menu > li.is-hovered .list-button:before {
content: ''; content: '';
position: absolute; position: absolute;
top: 4px; top: 4px;
@ -1993,7 +2025,8 @@ footer {
background: white; background: white;
} }
.user-menu li.add:hover .list-button:before { .user-menu li.add:hover .list-button:before,
.user-menu li.add.is-hovered .list-button:before {
background: #38ae6a; background: #38ae6a;
} }
@ -2013,6 +2046,7 @@ footer {
} }
.user-menu > li.add:hover .user-menu-icon.icon-plus, .user-menu > li.add:hover .user-menu-icon.icon-plus,
.user-menu > li.add.is-hovered .user-menu-icon.icon-plus,
.user-menu > li.add.active .user-menu-icon.icon-plus { .user-menu > li.add.active .user-menu-icon.icon-plus {
fill: white; fill: white;
} }
@ -3425,7 +3459,6 @@ footer {
.attachment-name { .attachment-name {
margin-right: 5px; margin-right: 5px;
word-break: break-all;
@extend .u-highlight; @extend .u-highlight;
} }
@ -4052,7 +4085,7 @@ footer {
border-radius: 0; border-radius: 0;
border: 1px solid hsl(0,0%,90%); border: 1px solid hsl(0,0%,90%);
box-shadow: none; box-shadow: none;
color: hsl(206,7%,28%); color: hsl(60,1%,34%);
word-wrap: break-word; word-wrap: break-word;
} }
@ -4079,6 +4112,7 @@ footer {
.modal-body { .modal-body {
padding: 0 23px; padding: 0 23px;
word-break: normal;
} }
.modal-footer { .modal-footer {
@ -4975,7 +5009,6 @@ label + .wizard-buttonList {
} }
.name { .name {
word-break: break-all;
@extend .u-highlight; @extend .u-highlight;
} }
} }

Binary file not shown.