Compact user menu

This commit is contained in:
John Firebaugh 2013-07-16 16:37:58 -07:00
parent 9701c6210c
commit 1727cd7c2b
10 changed files with 428 additions and 57 deletions

View file

@ -5,6 +5,7 @@ folder 'vendor/assets' do
folder 'bootstrap' do
file 'bootstrap.tooltip.js', 'https://raw.github.com/twbs/bootstrap/v2.3.2/js/bootstrap-tooltip.js'
file 'bootstrap.dropdown.js', 'https://raw.github.com/twbs/bootstrap/v2.3.2/js/bootstrap-dropdown.js'
end
folder 'leaflet' do

View file

@ -4,6 +4,7 @@
//= require jquery.cookie
//= require jquery.throttle-debounce
//= require bootstrap.tooltip
//= require bootstrap.dropdown
//= require augment
//= require osm
//= require leaflet

View file

@ -202,6 +202,7 @@ h6:first-child {
.icon.close { background-position: -200px 0; }
.icon.check { background-position: -220px 0; }
.icon.note { background-position: -240px 0; }
.icon.gear { background-position: -260px 0; }
/* Rules for links */
@ -472,7 +473,11 @@ a.donate {
height: 30px;
border-bottom: 1px solid #ccc;
background: white;
z-index: 100;
z-index: 1001;
.caret {
margin-top: 10px;
}
}
.site-edit #top-bar,
@ -544,12 +549,52 @@ a.donate {
#greeting {
float: right;
padding-top: 3px;
margin-right: $lineheight/4;
}
height: 100%;
.greeting-bar-unread {
font-weight: bold;
&.secondary-actions {
padding: 3px $lineheight/2;
}
&.dropdown {
background-color: #EEE;
&:hover {
background-color: #CCC;
}
}
img {
vertical-align: top;
border-radius: 2px 0 0 2px;
padding-right: 5px;
}
#inboxanchor {
display: inline-block;
position: relative;
height: 20px;
top: -2px;
margin: 0 2px 0 0;
padding: 0 5px 0 0;
border-radius: 2px;
}
.dropdown-toggle {
display: block;
padding: 3px 7px;
color: #000;
text-decoration: none;
}
.dropdown-menu {
left: auto;
right: 0;
.count-number {
float: right;
padding: 0 5px;
margin: 0;
}
}
}
/* Rules for the message shown in place of the map when javascript is disabled */
@ -2292,6 +2337,134 @@ a.button {
background: #fff;
}
/* Rules for dropdown menus */
.dropdown {
position: relative;
}
.dropdown-toggle {
*margin-bottom: -3px;
}
.dropdown-toggle:active,
.open .dropdown-toggle {
outline: 0;
}
.caret {
display: inline-block;
width: 0;
height: 0;
vertical-align: top;
border-top: 4px solid #000000;
border-right: 4px solid transparent;
border-left: 4px solid transparent;
content: "";
}
.dropdown .caret {
margin-top: 8px;
margin-left: 2px;
}
.dropdown-menu {
position: absolute;
top: 100%;
left: 0;
z-index: 1000;
display: none;
float: left;
min-width: 160px;
padding: 5px 0;
margin: 0;
list-style: none;
background-color: #ffffff;
border: 1px solid #ccc;
*border-right-width: 2px;
*border-bottom-width: 2px;
-webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
-moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
-webkit-background-clip: padding-box;
-moz-background-clip: padding;
background-clip: padding-box;
}
.dropdown-menu.pull-right {
right: 0;
left: auto;
}
.dropdown-menu .divider {
*width: 100%;
height: 1px;
margin: 9px 1px;
*margin: -5px 0 5px;
overflow: hidden;
background-color: #e5e5e5;
border-bottom: 1px solid #ffffff;
}
.dropdown-menu > li > a {
display: block;
padding: 3px 10px;
clear: both;
font-weight: normal;
line-height: 20px;
color: #333333;
white-space: nowrap;
}
.dropdown-menu > li > a:hover,
.dropdown-menu > li > a:focus,
.dropdown-submenu:hover > a,
.dropdown-submenu:focus > a {
color: #ffffff;
text-decoration: none;
background-color: #0081c2;
}
.dropdown-menu > .active > a,
.dropdown-menu > .active > a:hover,
.dropdown-menu > .active > a:focus {
color: #ffffff;
text-decoration: none;
background-color: #0081c2;
outline: 0;
}
.dropdown-menu > .disabled > a,
.dropdown-menu > .disabled > a:hover,
.dropdown-menu > .disabled > a:focus {
color: #999999;
}
.dropdown-menu > .disabled > a:hover,
.dropdown-menu > .disabled > a:focus {
text-decoration: none;
cursor: default;
background-color: transparent;
background-image: none;
}
.open {
*z-index: 1000;
}
.open > .dropdown-menu {
display: block;
}
.dropdown-backdrop {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 990;
}
/* Rules for the "Welcome" page */
.site-welcome {
.center {

View file

@ -84,13 +84,6 @@ h2, h3, h4 {
/* Rules for greeting bar in the top right corner */
#greeting {
position: absolute;
right: 0;
top: 0;
background: none;
}
#browse_map ul.secondary-actions {
float: right;
font-size: 10px;
@ -267,4 +260,4 @@ p.search_results_entry {
.aside {
display: none;
}
}
}

View file

@ -1,13 +1,3 @@
<%=
link_to(
t("layouts.inbox_html",
:count => @user.new_messages.size > 0 ?
content_tag(
:span, @user.new_messages.size, :class => "count-number"
) :
""
),
inbox_path(:display_name => @user.display_name),
:id => "inboxanchor"
)
%>
<span id="inboxanchor" class="count-number">
<img src='<%= user_image_url(@user, :size => 20) %>'><span><%= @user.new_messages.size %></span>
</span>

View file

@ -0,0 +1,55 @@
<div class='dropdown' id='greeting'>
<a class='dropdown-toggle' data-toggle='dropdown' href="#">
<%= render :partial => 'layouts/inbox' %>
<%= @user.display_name %>
<b class="caret"></b>
</a>
<ul class='dropdown-menu' role='menu' aria-labelledby='dLabel'>
<li>
<%= link_to inbox_path(:display_name => @user.display_name) do %>
<span class='count-number'><%= number_with_delimiter(@user.new_messages.size) %></span>
<%= t('message.inbox.my_inbox') %>
<% end %>
</li>
<li>
<%= link_to :controller => 'changeset', :action => 'list', :display_name => @user.display_name do %>
<span class='count-number'><%= number_with_delimiter(@user.changesets.size) %></span>
<%= t('user.view.my edits') %>
<% end %>
</li>
<li>
<%= link_to :controller => 'notes', :action => 'mine', :display_name => @user.display_name do %>
<span class='count-number'><%= number_with_delimiter(@user.notes.size) %></span>
<%= t('user.view.my notes') %>
<% end %>
</li>
<li>
<%= link_to :controller => 'trace', :action => 'mine' do %>
<span class='count-number'><%= number_with_delimiter(@user.traces.size) %></span>
<%= t('user.view.my traces') %>
<% end %>
</li>
<li>
<%= link_to :controller => 'diary_entry', :action => 'list', :display_name => @user.display_name do %>
<span class='count-number'><%= number_with_delimiter(@user.diary_entries.size) %></span>
<%= t('user.view.my diary') %>
<% end %>
</li>
<li>
<%= link_to t('user.view.my comments' ), :controller => 'diary_entry', :action => 'comments', :display_name => @user.display_name %>
</li>
<li>
<%= link_to t('user.view.my profile'), user_path(:display_name => @user.display_name) %>
</li>
<li>
<%= link_to t('user.view.my settings'), :controller => 'user', :action => 'account', :display_name => @user.display_name %>
</li>
<li class="divider"></li>
<li>
<%= yield :greeting %>
</li>
<li>
<%= link_to t('layouts.logout'), logout_path(:session => request.session_options[:id], :referer => request.fullpath) %>
</li>
</ul>
</div>

View file

@ -99,17 +99,14 @@
</div>
</div>
<div id='top-bar'>
<ul class='secondary-actions' id="greeting">
<% if @user and @user.id %>
<li id="full-greeting"><%=link_to h(@user.display_name), user_path(:display_name => @user.display_name), :title => t('layouts.welcome_user_link_tooltip') %></li>
<li><%= yield :greeting %></li>
<li><%= render :partial => "layouts/inbox" %></li>
<li><%= link_to t('layouts.logout'), logout_path(:session => request.session_options[:id], :referer => request.fullpath), {:id => 'logoutanchor', :title => t('layouts.logout_tooltip')}%></li>
<% else %>
<li><%= link_to t('layouts.log_in'), login_path(:referer => request.fullpath), {:id => 'loginanchor', :title => t('layouts.log_in_tooltip')} %></li>
<li><%= link_to t('layouts.sign_up'), user_new_path, {:id => 'registeranchor', :title => t('layouts.sign_up_tooltip')} %></li>
<% end %>
</ul>
<% if @user and @user.id %>
<%= render :partial => "layouts/user_menu" %>
<% else %>
<ul class='secondary-actions' id='greeting'>
<li><%= link_to t('layouts.log_in'), login_path(:referer => request.fullpath), {:id => 'loginanchor', :title => t('layouts.log_in_tooltip')} %></li>
<li><%= link_to t('layouts.sign_up'), user_new_path, {:id => 'registeranchor', :title => t('layouts.sign_up_tooltip')} %></li>
</ul>
<% end %>
<ul id="tabnav">
<li><%= link_to t('layouts.view'), root_path, {
:id => 'viewanchor',

View file

@ -6,7 +6,6 @@
:class => "set_position",
:data => { :lat => @user.home_lat,
:lon => @user.home_lon,
:zoom => 15 },
:title => t("layouts.home_tooltip") %>
:zoom => 15 } %>
<% end %>
<% end %>

View file

@ -996,16 +996,8 @@ en:
h1: OpenStreetMap
logo:
alt_text: OpenStreetMap logo
welcome_user_link_tooltip: Your user page
home: home
home_tooltip: Go to home location
inbox_html: "inbox %{count}"
inbox_tooltip:
zero: Your inbox contains no unread messages
one: Your inbox contains 1 unread message
other: Your inbox contains %{count} unread messages
logout: logout
logout_tooltip: "Log out"
home: Go to Home Location
logout: Logout
log_in: log in
log_in_tooltip: Log in with an existing account
sign_up: sign up
@ -1294,7 +1286,7 @@ en:
message:
inbox:
title: "Inbox"
my_inbox: "My inbox"
my_inbox: "My Inbox"
outbox: "outbox"
messages: "You have %{new_messages} and %{old_messages}"
new_messages:
@ -1777,13 +1769,14 @@ en:
heading: "The user %{user} does not exist"
body: "Sorry, there is no user with the name %{user}. Please check your spelling, or maybe the link you clicked is wrong."
view:
my diary: my diary
my diary: My Diary
new diary entry: new diary entry
my edits: my edits
my traces: my traces
my notes: my map notes
my settings: my settings
my comments: my comments
my edits: My Edits
my traces: My Traces
my notes: My Notes
my profile: My Profile
my settings: My Settings
my comments: My Comments
oauth settings: oauth settings
blocks on me: blocks on me
blocks by me: blocks by me

View file

@ -0,0 +1,169 @@
/* ============================================================
* bootstrap-dropdown.js v2.3.2
* http://getbootstrap.com/2.3.2/javascript.html#dropdowns
* ============================================================
* Copyright 2013 Twitter, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ============================================================ */
!function ($) {
"use strict"; // jshint ;_;
/* DROPDOWN CLASS DEFINITION
* ========================= */
var toggle = '[data-toggle=dropdown]'
, Dropdown = function (element) {
var $el = $(element).on('click.dropdown.data-api', this.toggle)
$('html').on('click.dropdown.data-api', function () {
$el.parent().removeClass('open')
})
}
Dropdown.prototype = {
constructor: Dropdown
, toggle: function (e) {
var $this = $(this)
, $parent
, isActive
if ($this.is('.disabled, :disabled')) return
$parent = getParent($this)
isActive = $parent.hasClass('open')
clearMenus()
if (!isActive) {
if ('ontouchstart' in document.documentElement) {
// if mobile we we use a backdrop because click events don't delegate
$('<div class="dropdown-backdrop"/>').insertBefore($(this)).on('click', clearMenus)
}
$parent.toggleClass('open')
}
$this.focus()
return false
}
, keydown: function (e) {
var $this
, $items
, $active
, $parent
, isActive
, index
if (!/(38|40|27)/.test(e.keyCode)) return
$this = $(this)
e.preventDefault()
e.stopPropagation()
if ($this.is('.disabled, :disabled')) return
$parent = getParent($this)
isActive = $parent.hasClass('open')
if (!isActive || (isActive && e.keyCode == 27)) {
if (e.which == 27) $parent.find(toggle).focus()
return $this.click()
}
$items = $('[role=menu] li:not(.divider):visible a', $parent)
if (!$items.length) return
index = $items.index($items.filter(':focus'))
if (e.keyCode == 38 && index > 0) index-- // up
if (e.keyCode == 40 && index < $items.length - 1) index++ // down
if (!~index) index = 0
$items
.eq(index)
.focus()
}
}
function clearMenus() {
$('.dropdown-backdrop').remove()
$(toggle).each(function () {
getParent($(this)).removeClass('open')
})
}
function getParent($this) {
var selector = $this.attr('data-target')
, $parent
if (!selector) {
selector = $this.attr('href')
selector = selector && /#/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
}
$parent = selector && $(selector)
if (!$parent || !$parent.length) $parent = $this.parent()
return $parent
}
/* DROPDOWN PLUGIN DEFINITION
* ========================== */
var old = $.fn.dropdown
$.fn.dropdown = function (option) {
return this.each(function () {
var $this = $(this)
, data = $this.data('dropdown')
if (!data) $this.data('dropdown', (data = new Dropdown(this)))
if (typeof option == 'string') data[option].call($this)
})
}
$.fn.dropdown.Constructor = Dropdown
/* DROPDOWN NO CONFLICT
* ==================== */
$.fn.dropdown.noConflict = function () {
$.fn.dropdown = old
return this
}
/* APPLY TO STANDARD DROPDOWN ELEMENTS
* =================================== */
$(document)
.on('click.dropdown.data-api', clearMenus)
.on('click.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() })
.on('click.dropdown.data-api' , toggle, Dropdown.prototype.toggle)
.on('keydown.dropdown.data-api', toggle + ', [role=menu]' , Dropdown.prototype.keydown)
}(window.jQuery);