Bug 9420 [Revised] Work on Bootstrap for Koha

YUI JS is deprecated as far as Koha is concerned, and jQueryUI menus
don't seem to be as robust as they should be. This makes Twitter
Bootstrap very attrative for its menus features as well as other
aspects.

This patch revises the staff client header menu to include features from
Bootstrap, including replacement of the YUI-driven "More..." menu with a
Bootstrap version, and a new user menu taken from Corey Fuimaono's
similar patch.

To test, be sure to clear your cache after applying the patch. Load any
page in the staff client and confirm that the menu at the top of the
screen looks correct and works as normal, including functionality of the
"more" menu. Confirm that the username/logged-in branch triggers a menu
with "set library" and "log out" options. Confirm that Cart operations
trigger the correct confirmation popup.

Revision moves the Bootstrap assets out of the prog template into
koha-tmpl/intranet-tmpl/lib.

Signed-off-by: Bernardo Gonzalez Kriegel <bgkriegel@gmail.com>

Works great. No errors.

Signed-off-by: Jonathan Druart <jonathan.druart@biblibre.com>
Signed-off-by: Jared Camins-Esakov <jcamins@cpbibliography.com>
This commit is contained in:
Owen Leonard 2013-01-25 13:57:28 -05:00 committed by Jared Camins-Esakov
parent a386df2c78
commit ecf42ffbd0
9 changed files with 841 additions and 140 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View file

@ -143,6 +143,7 @@ em strong {
#login_controls { #login_controls {
position : absolute; position : absolute;
right : .5em; right : .5em;
padding: .4em .5em;
} }
ul { ul {
@ -165,15 +166,6 @@ ol li {
list-style : decimal; list-style : decimal;
} }
#header {
background-color : #e6f0f2;
line-height : 2em;
}
#header a.toplinks {
font-weight: bold;
}
.gradient { .gradient {
background-image: linear-gradient(top, rgb(230,240,242) 1%, rgb(255,255,255) 99%); background-image: linear-gradient(top, rgb(230,240,242) 1%, rgb(255,255,255) 99%);
background-image: -o-linear-gradient(top, rgb(230,240,242) 1%, rgb(255,255,255) 99%); background-image: -o-linear-gradient(top, rgb(230,240,242) 1%, rgb(255,255,255) 99%);
@ -1114,6 +1106,8 @@ div.alert {
background: linear-gradient(top, #fef8d3 0%,#ffec91 9%,#ffed87 89%,#f9dc00 100%); /* W3C */ background: linear-gradient(top, #fef8d3 0%,#ffec91 9%,#ffed87 89%,#f9dc00 100%); /* W3C */
text-align : center; text-align : center;
border: 1px solid #E0C726; border: 1px solid #E0C726;
color : inherit;
text-shadow : none;
} }
div.alert strong { div.alert strong {
@ -1617,16 +1611,16 @@ a.yuimenuitemlabel:hover {
vertical-align : top; vertical-align : top;
} }
#toplevelnav { ul#toplevelmenu {
padding : 0;
}
/*#toplevelnav {
float : left; float : left;
margin-left : .5em; margin-left : .5em;
width: 40%; width: 40%;
} }
ul#toplevelmenu {
padding : 0;
}
ul#toplevelmenu li { ul#toplevelmenu li {
display: inline; display: inline;
padding : 0 .6em; padding : 0 .6em;
@ -1735,7 +1729,7 @@ div.lang {
* html div#doc3{ * html div#doc3{
height:100%; height:100%;
overflow:auto; overflow:auto;
} }*/
#CheckAll, #CheckNone, #CheckPending { #CheckAll, #CheckNone, #CheckPending {
font-weight : normal; font-weight : normal;
@ -1845,7 +1839,7 @@ span.permissiondesc {
z-index : 50; z-index : 50;
} }
#cartmenulink { #cartmenulink {
background: transparent url("../../img/cart-small.gif") 0 3px no-repeat; background: transparent url("../../img/cart-small.gif") left center no-repeat;
padding-left : 15px; padding-left : 15px;
} }
#cartmenulink span#basketcount span { #cartmenulink span#basketcount span {
@ -2401,3 +2395,117 @@ div.authorizedheading {
video { video {
width: 480px; width: 480px;
} }
/* Bootstrap overrides */
.btn {
border-color : #ADADAD #ADADAD #949494;
}
#toolbar .btn,
#toolbar .dropdown-menu {
font-size: 13px;
}
a.btn:link,
a.btn:visited{
color: #333333;
}
.dropdown-menu li {
list-style: none outside none;
}
[class^="icon-"],[class*=" icon-"]{background-image:url("../../img/glyphicons-halflings.png");}
.icon-white,.nav-tabs>.active>a>[class^="icon-"],.nav-tabs>.active>a>[class*=" icon-"],.nav-pills>.active>a>[class^="icon-"],.nav-pills>.active>a>[class*=" icon-"],.nav-list>.active>a>[class^="icon-"],.nav-list>.active>a>[class*=" icon-"],.navbar-inverse .nav>.active>a>[class^="icon-"],.navbar-inverse .nav>.active>a>[class*=" icon-"],.dropdown-menu>li>a:hover>[class^="icon-"],.dropdown-menu>li>a:hover>[class*=" icon-"],.dropdown-menu>.active>a>[class^="icon-"],.dropdown-menu>.active>a>[class*=" icon-"]{background-image:url("../../img/glyphicons-halflings-white.png");}
a.disabled {
color : #999999;
}
.navbar {
color: #333;
}
.navbar .nav > li > a {
color: #004D99;
font-weight: bold;
padding : .4em .2em;
}
.navbar .nav > li {
list-style: none outside none;
padding : 0 .6em;
}
.navbar .nav > li > a:focus,
.navbar .nav > li > a:hover {
color: #538200;
}
.navbar .nav li.dropdown.open > .dropdown-toggle,
.navbar .nav li.dropdown.active > .dropdown-toggle,
.navbar .nav li.dropdown.open.active > .dropdown-toggle {
background: transparent none;
}
.navbar-static-top .navbar-inner {
background: #E6F0F2 none;
border: 0;
box-shadow: none;
min-height: 0;
padding-left: 0;
}
.navbar-fixed-bottom .navbar-inner {
min-height: 0;
padding : .4em 0;
}
.navbar-fixed-bottom .nav > li > a {
font-weight: normal;
padding : .05em .3em;
}
.navbar-fixed-bottom .nav > li {
border-right : 1px solid #CCC;
}
.navbar-fixed-bottom .nav > li:last-child {
border-right : 0;
}
.navbar-fixed-bottom .nav > li.navbar-text {
line-height: normal;
padding : 0.4em 0.7em;
}
.navbar .nav > li {
list-style: none outside none;
padding : 0 .6em;
}
.navbar .nav > li > a {
color: #004D99;
font-weight: bold;
padding : .4em .3em;
}
.navbar .nav li.dropdown.open > .dropdown-toggle, .navbar .nav li.dropdown.active > .dropdown-toggle, .navbar .nav li.dropdown.open.active > .dropdown-toggle {
background: transparent none;
}
.navbar .nav > li > a:focus,
.navbar .nav > li > a:hover {
color: #538200;
}
.navbar .nav li.dropdown.open > .dropdown-toggle,
.navbar .nav li.dropdown.active > .dropdown-toggle,
.navbar .nav li.dropdown.open.active > .dropdown-toggle {
background: transparent none;
}
.tooltip.bottom .tooltip-arrow {
border-bottom-color: #EEE;
}
.tooltip.bottom .tooltip-inner {
background-color : #FFF;
border: 1px solid rgba(0, 0, 0, 0.2);
box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
color: #000;
padding : 1em;
font-size : 120%;
}
.separator { color : #666; padding : 0 .2em; }

View file

@ -1,6 +1,7 @@
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<link rel="shortcut icon" href="[% IF ( IntranetFavicon ) %][% IntranetFavicon %][% ELSE %][% themelang %]/includes/favicon.ico[% END %]" type="image/x-icon" /> <link rel="shortcut icon" href="[% IF ( IntranetFavicon ) %][% IntranetFavicon %][% ELSE %][% themelang %]/includes/favicon.ico[% END %]" type="image/x-icon" />
<link rel="stylesheet" type="text/css" href="[% interface %]/lib/jquery/jquery-ui.css" /> <link rel="stylesheet" type="text/css" href="[% interface %]/lib/jquery/jquery-ui.css" />
<link rel="stylesheet" type="text/css" href="[% interface %]/lib/bootstrap/bootstrap.min.css" />
<link rel="stylesheet" type="text/css" media="print" href="[% themelang %]/css/print.css" /> <link rel="stylesheet" type="text/css" media="print" href="[% themelang %]/css/print.css" />
[% IF ( intranetstylesheet ) %] [% IF ( intranetstylesheet ) %]
<link rel="stylesheet" type="text/css" href="[% intranetstylesheet %]" /> <link rel="stylesheet" type="text/css" href="[% intranetstylesheet %]" />
@ -13,6 +14,8 @@
<script type="text/javascript" src="[% interface %]/lib/jquery/plugins/jquery.hotkeys.min.js"></script> <script type="text/javascript" src="[% interface %]/lib/jquery/plugins/jquery.hotkeys.min.js"></script>
<script type="text/javascript" src="[% interface %]/lib/jquery/plugins/jquery.cookie.min.js"></script> <script type="text/javascript" src="[% interface %]/lib/jquery/plugins/jquery.cookie.min.js"></script>
<script type="text/javascript" src="[% interface %]/lib/jquery/plugins/jquery.highlight-3.js"></script> <script type="text/javascript" src="[% interface %]/lib/jquery/plugins/jquery.highlight-3.js"></script>
<script type="text/javascript" src="[% interface %]/lib/bootstrap/bootstrap.min.js"></script>
[% IF ( login ) %] [% IF ( login ) %]
<link rel="stylesheet" type="text/css" href="[% themelang %]/css/login.css" /> <link rel="stylesheet" type="text/css" href="[% themelang %]/css/login.css" />
[% END %] [% END %]

View file

@ -1,20 +1,16 @@
[% IF ( intranetbookbag ) %]<div id="cartDetails">Your cart is empty.</div>[% END %] <div id="header" class="navbar navbar-static-top">
<div class="navbar-inner">
<div id="header" class="clearfix"> <ul id="toplevelmenu" class="nav">
<div id="toplevelnav"> [% IF ( CAN_user_circulate ) %]<li><a href="/cgi-bin/koha/circ/circulation-home.pl">Circulation</a></li>[% END %]
<ul id="toplevelmenu"> [% IF ( CAN_user_borrowers ) %]<li><a href="/cgi-bin/koha/members/members-home.pl">Patrons</a></li>[% END %]
[% IF ( CAN_user_circulate ) %]<li><a class="toplinks" href="/cgi-bin/koha/circ/circulation-home.pl">Circulation</a></li>[% END %] [% IF ( CAN_user_catalogue ) %]<li><a href="/cgi-bin/koha/catalogue/search.pl">Search</a></li>[% END %]
[% IF ( CAN_user_borrowers ) %]<li><a class="toplinks" href="/cgi-bin/koha/members/members-home.pl">Patrons</a></li>[% END %]
[% IF ( CAN_user_catalogue ) %]<li><a class="toplinks" href="/cgi-bin/koha/catalogue/search.pl">Search</a></li>[% END %]
[% IF ( intranetbookbag ) %] [% IF ( intranetbookbag ) %]
<li><a class="toplinks" href="#" id="cartmenulink">Cart<span id="basketcount"></span></a></li> <li><a href="#" id="cartmenulink">Cart<span id="basketcount"></span></a></li>
[% END %] [% END %]
[% IntranetNav %] [% IntranetNav %]
<li class="more"> <li class="dropdown">
<a class="toplinks" id="showmore" href="/cgi-bin/koha/mainpage.pl">More</a> <a href="#" class="dropdown-toggle" data-toggle="dropdown">More <b class="caret"></b></a>
<div id="moremenu"> <ul class="dropdown-menu">
<div class="bd">
<ul>
<li><a href="/cgi-bin/koha/virtualshelves/shelves.pl">Lists</a></li> <li><a href="/cgi-bin/koha/virtualshelves/shelves.pl">Lists</a></li>
[% IF ( CAN_user_editcatalogue_edit_catalogue || CAN_user_editcatalogue_edit_items ) %] [% IF ( CAN_user_editcatalogue_edit_catalogue || CAN_user_editcatalogue_edit_items ) %]
<li><a href="/cgi-bin/koha/cataloguing/addbooks.pl">Cataloging</a></li> <li><a href="/cgi-bin/koha/cataloguing/addbooks.pl">Cataloging</a></li>
@ -39,45 +35,62 @@
[% END %] [% END %]
<li><a href="/cgi-bin/koha/about.pl">About Koha</a></li> <li><a href="/cgi-bin/koha/about.pl">About Koha</a></li>
</ul> </ul>
</div>
</div>
</li> </li>
</ul> </ul>
</div> <ul class="nav pull-right">
<div id="login_controls"> <li class="dropdown">
[% IF ( AutoLocation ) %] <a href="#" id="drop3" role="button" class="dropdown-toggle" data-toggle="dropdown">
<strong> [% IF ( loggedinusername ) %]
[% LoginBranchname %] <span class="loggedinusername">
</strong> [% loggedinusername %]
[% ELSE %] </span>
<strong> <span class="separator">|</span>
[% IF ( LoginBranchname == 'NO_LIBRARY_SET' ) %] [% IF ( AutoLocation ) %]
NO LIBRARY SET <brand>
[% ELSE %] [% LoginBranchname %]
[% LoginBranchname %] </brand>
[% END %] [% ELSE %]
</strong> <strong>
[% IF ( IndependantBranches ) %] [% IF ( LoginBranchname == 'NO_LIBRARY_SET' ) %]
[% IF ( CAN_user_management || CAN_user_editcatalogue_edit_catalogue ) %] NO LIBRARY SET
( <a class="toplinks" href="/cgi-bin/koha/circ/selectbranchprinter.pl">Set library</a> ) [% ELSE %]
[% END %] [% LoginBranchname %]
[% ELSE %] [% END %]
( <a class="toplinks" href="/cgi-bin/koha/circ/selectbranchprinter.pl">Set library</a> ) </strong>
[% END %] [% END %]
| <b class="caret"></b>
[% END %] </a>
[% IF ( loggedinusername ) %] <ul class="dropdown-menu" role="menu" aria-labelledby="drop3">
<span class="loggedinusername"> [% IF ( IndependantBranches ) %]
[% loggedinusername %] [% IF ( CAN_user_management || CAN_user_editcatalogue_edit_catalogue ) %]
</span> <li>
[% IF ( intranetbookbag ) %] <a class="toplinks" href="/cgi-bin/koha/circ/selectbranchprinter.pl">Set library</a>
( <a class="toplinks" href="/cgi-bin/koha/mainpage.pl?logout.x=1" onclick="clearHoldFor(); delBasket('main', true);">Log out</a> ) | </li>
[% ELSE %] [% END %]
( <a class="toplinks" href="/cgi-bin/koha/mainpage.pl?logout.x=1" onclick="clearHoldFor();">Log out</a> ) | [% ELSE %]
[% END %] <li>
[% ELSE %] <a class="toplinks" href="/cgi-bin/koha/circ/selectbranchprinter.pl">Set library</a>
You are not logged in | </li>
[% END %] [% END %]
<a class="toplinks" href="/cgi-bin/koha/help.pl" id="helper" onclick="var link=window.open('','Koha_Help','width=600,height=600,toolbar=false,scrollbars=yes'); link.location='/cgi-bin/koha/help.pl'; return false;">Help</a> [% IF ( intranetbookbag ) %]
</div> <li>
</div> <a class="toplinks" href="/cgi-bin/koha/mainpage.pl?logout.x=1" onclick="clearHoldFor(); delBasket('main', true);">Log out</a>
</li>
[% ELSE %]
<li>
<a class="toplinks" href="/cgi-bin/koha/mainpage.pl?logout.x=1" onclick="clearHoldFor();">Log out</a>
</li>
[% END %]
[% ELSE %]
You are not logged in |
[% END %]
</ul>
<li>
<a class="toplinks" href="/cgi-bin/koha/help.pl" id="helper" onclick="var link=window.open('','Koha_Help','width=600,height=600,toolbar=false,scrollbars=yes'); link.location='/cgi-bin/koha/help.pl'; return false;">Help</a>
</li>
</li>
</ul>
</div>
</div>
[% IF ( intranetbookbag ) %]<div id="cartDetails">Your cart is empty.</div>[% END %]
</div>

View file

@ -2,14 +2,15 @@
[% IF ( languages_loop ) %] [% IF ( languages_loop ) %]
[% UNLESS ( one_language_enabled ) %] [% UNLESS ( one_language_enabled ) %]
<div id="changelanguage" class="ft"> <div id="changelanguage" class="navbar navbar-fixed-bottom">
<ul id="i18nMenu" class="footermenu"> <div class="navbar-inner">
<ul id="i18nMenu" class="nav">
[% FOREACH languages_loo IN languages_loop %] [% FOREACH languages_loo IN languages_loop %]
[% IF ( languages_loo.group_enabled ) %] [% IF ( languages_loo.group_enabled ) %]
[% IF ( languages_loo.plural ) %] [% IF ( languages_loo.plural ) %]
<li class="more"><a class="sublangs" id="show[% languages_loo.rfc4646_subtag %]" href="#">[% languages_loo.native_description %] ([% languages_loo.rfc4646_subtag %])</a><div id="sub[% languages_loo.rfc4646_subtag %]"> <li class="dropdown"><a class="dropdown-toggle dropup" data-toggle="dropdown" id="show[% languages_loo.rfc4646_subtag %]" href="#">[% languages_loo.native_description %] ([% languages_loo.rfc4646_subtag %]) <span class="caret"></span></a>
<div class="bd"><ul> <ul id="sub[% languages_loo.rfc4646_subtag %]" class="dropdown-menu">
[% FOREACH sublanguages_loo IN languages_loo.sublanguages_loop %] [% FOREACH sublanguages_loo IN languages_loo.sublanguages_loop %]
[% IF ( sublanguages_loo.enabled ) %] [% IF ( sublanguages_loo.enabled ) %]
[% IF ( sublanguages_loo.sublanguage_current ) %] [% IF ( sublanguages_loo.sublanguage_current ) %]
@ -20,14 +21,26 @@
[% END %] [% END %]
[% END %] [% END %]
</ul></div></div></li> </ul></li>
[% ELSE %] [% ELSE %]
[% IF ( languages_loo.group_enabled ) %] [% IF ( languages_loo.group_enabled ) %]
[% IF ( languages_loo.current ) %] [% IF ( languages_loo.current ) %]
<li>[% IF ( languages_loo.native_description ) %][% languages_loo.native_description %][% ELSE %][% languages_loo.rfc4646_subtag %][% END %]</li> <li class="navbar-text">
[% IF ( languages_loo.native_description ) %]
[% languages_loo.native_description %]
[% ELSE %] [% ELSE %]
<li><a href="/cgi-bin/koha/changelanguage.pl?language=[% languages_loo.rfc4646_subtag %]">[% IF ( languages_loo.native_description ) %][% languages_loo.native_description %][% ELSE %][% languages_loo.rfc4646_subtag %][% END %]</a></li> [% languages_loo.rfc4646_subtag %]
[% END %]
</li>
[% ELSE %]
<li><a href="/cgi-bin/koha/changelanguage.pl?language=[% languages_loo.rfc4646_subtag %]">
[% IF ( languages_loo.native_description ) %]
[% languages_loo.native_description %]
[% ELSE %]
[% languages_loo.rfc4646_subtag %]
[% END %]
</a></li>
[% END %] [% END %]
[% END %] [% END %]
[% END %] [% END %]
@ -36,6 +49,7 @@
[% END %] [% END %]
</ul> </ul>
</div> </div>
</div>
[% END %] [% END %]
[% END %] [% END %]
</body> </body>

View file

@ -1,7 +1,7 @@
// staff-global.js // staff-global.js
if ( KOHA === undefined ) var KOHA = {}; if ( KOHA === undefined ) var KOHA = {};
function _(s) { return s } // dummy function for gettext function _(s) { return s; } // dummy function for gettext
$(document).ready(function() { $(document).ready(function() {
$('#header_search').tabs().bind('tabsshow', function(e, ui) { $('#header_search > div:not(.ui-tabs-hide)').find('input').eq(0).focus(); }); $('#header_search').tabs().bind('tabsshow', function(e, ui) { $('#header_search > div:not(.ui-tabs-hide)').find('input').eq(0).focus(); });
@ -10,69 +10,9 @@ function _(s) { return s } // dummy function for gettext
if($("#header_search #circ_search").length > 0){ $(document).bind('keydown','Alt+u',function (){ $("#header_search").tabs("select","#circ_search"); $("#findborrower").focus(); }); } else { $(document).bind('keydown','Alt+u',function(){ location.href="/cgi-bin/koha/circ/circulation.pl"; }); } if($("#header_search #circ_search").length > 0){ $(document).bind('keydown','Alt+u',function (){ $("#header_search").tabs("select","#circ_search"); $("#findborrower").focus(); }); } else { $(document).bind('keydown','Alt+u',function(){ location.href="/cgi-bin/koha/circ/circulation.pl"; }); }
if($("#header_search #catalog_search").length > 0){ $(document).bind('keydown','Alt+q',function (){ $("#header_search").tabs("select","#catalog_search"); $("#search-form").focus(); }); } else { $(document).bind('keydown','Alt+q',function(){ location.href="/cgi-bin/koha/catalogue/search.pl"; }); } if($("#header_search #catalog_search").length > 0){ $(document).bind('keydown','Alt+q',function (){ $("#header_search").tabs("select","#catalog_search"); $("#search-form").focus(); }); } else { $(document).bind('keydown','Alt+q',function(){ location.href="/cgi-bin/koha/catalogue/search.pl"; }); }
$(".focus").focus(); $(".focus").focus();
});
YAHOO.util.Event.onContentReady("header", function () {
var oMoremenu = new YAHOO.widget.Menu("moremenu", { zindex: 2 });
function positionoMoremenu() {
oMoremenu.align("tl", "bl");
}
oMoremenu.subscribe("beforeShow", function () {
if (this.getRoot() == this) {
positionoMoremenu();
}
});
oMoremenu.render();
oMoremenu.cfg.setProperty("context", ["showmore", "tl", "bl"]);
function onShowMoreClick(p_oEvent) {
// Position and display the menu
positionoMoremenu();
$("#moremenu").show();
oMoremenu.show();
// Stop propagation and prevent the default "click" behavior
YAHOO.util.Event.stopEvent(p_oEvent);
}
YAHOO.util.Event.addListener("showmore", "click", onShowMoreClick);
YAHOO.widget.Overlay.windowResizeEvent.subscribe(positionoMoremenu);
});
// build Change Language menus
YAHOO.util.Event.onContentReady("changelanguage", function () {
$(".sublangs").each(function(){
var menuid = $(this).attr("id");
var menuid = menuid.replace("show","");
var oMenu = new YAHOO.widget.Menu("sub"+menuid, { zindex: 2 });
function positionoMenu() {
oMenu.align("bl", "tl");
}
oMenu.subscribe("beforeShow", function () {
if (this.getRoot() == this) {
positionoMenu();
}
});
oMenu.render();
oMenu.cfg.setProperty("context", ["show"+menuid, "bl", "tl"]);
function onYahooClick(p_oEvent) {
// Position and display the menu
positionoMenu();
oMenu.show();
// Stop propagation and prevent the default "click" behavior
YAHOO.util.Event.stopEvent(p_oEvent);
}
YAHOO.util.Event.addListener("show"+menuid, "click", onYahooClick);
YAHOO.widget.Overlay.windowResizeEvent.subscribe(positionoMenu);
});
}); });
// http://jennifermadden.com/javascript/stringEnterKeyDetector.html // http://jennifermadden.com/javascript/stringEnterKeyDetector.html
function checkEnter(e){ //e is event object passed from function invocation function checkEnter(e){ //e is event object passed from function invocation
var characterCode; // literal character code will be stored in this variable var characterCode; // literal character code will be stored in this variable