Compact user menu
This commit is contained in:
parent
9701c6210c
commit
1727cd7c2b
10 changed files with 428 additions and 57 deletions
|
@ -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
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
//= require jquery.cookie
|
||||
//= require jquery.throttle-debounce
|
||||
//= require bootstrap.tooltip
|
||||
//= require bootstrap.dropdown
|
||||
//= require augment
|
||||
//= require osm
|
||||
//= require leaflet
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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>
|
55
app/views/layouts/_user_menu.html.erb
Normal file
55
app/views/layouts/_user_menu.html.erb
Normal 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>
|
|
@ -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',
|
||||
|
|
|
@ -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 %>
|
||||
|
|
|
@ -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
|
||||
|
|
169
vendor/assets/bootstrap/bootstrap.dropdown.js
vendored
Normal file
169
vendor/assets/bootstrap/bootstrap.dropdown.js
vendored
Normal 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);
|
Loading…
Add table
Add a link
Reference in a new issue