summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeif Johansson <leifj@sunet.se>2011-07-26 17:20:34 +0200
committerLeif Johansson <leifj@sunet.se>2011-07-26 17:20:34 +0200
commite67f4e7b19d3c78b07ca26662e83c506b2c2cfa4 (patch)
tree9de3ab2d19043b9de2df234624dc90f16d3d14cc
parent33275b725e24a48dead511c667693b4d5114b66b (diff)
try mcdropdown instead
-rw-r--r--src/main/webapp/css/jquery.mcdropdown.min.css1
-rw-r--r--src/main/webapp/images/mcdropdown/mcdd_icon_hover.gifbin0 -> 333 bytes
-rw-r--r--src/main/webapp/images/mcdropdown/mcdd_icon_normal.gifbin0 -> 121 bytes
-rw-r--r--src/main/webapp/images/mcdropdown/mcdd_select_button_sprite.gifbin0 -> 1495 bytes
-rw-r--r--src/main/webapp/images/mcdropdown/shadow.pngbin0 -> 6117 bytes
-rw-r--r--src/main/webapp/js/jquery.bgiframe.js100
-rw-r--r--src/main/webapp/js/jquery.mcdropdown.js1139
-rw-r--r--src/main/webapp/js/jquery.mcdropdown.min.js22
-rw-r--r--src/main/webapp/wayf-ndn.jsp14
9 files changed, 1272 insertions, 4 deletions
diff --git a/src/main/webapp/css/jquery.mcdropdown.min.css b/src/main/webapp/css/jquery.mcdropdown.min.css
new file mode 100644
index 0000000..12ec51e
--- /dev/null
+++ b/src/main/webapp/css/jquery.mcdropdown.min.css
@@ -0,0 +1 @@
+div.mcdropdown{position:absolute;border:1px solid #8e9daa;padding:1px;display:-moz-inline-block;display:inline-block;width:408px;height:14px;padding:2px;}div.mcdropdown input,div.mcdropdown div{position:absolute;background-color:#fff;left:0;top:0;width:98%;border:0;padding:2px 0 0 3px;font:11px Arial,Helvetica,sans-serif;}div.mcdropdown a{position:absolute;right:1px;top:1px;background:transparent url(../images/mcdropdown/mcdd_select_button_sprite.gif) no-repeat top left;display:-moz-inline-block;display:inline-block;height:16px;width:15px;text-decoration:none;font-size:0;z-index:2;outline:0;}div.mcdropdown a:hover,div.mcdropdown a:focus{background-position:0 -16px;}div.mcdropdown a:active{background-position:0 -32px;outline:none;}div.mcdropdownDisabled{background-color:#e1e0e0;filter:alpha(opacity=75);-moz-opacity:.75;opacity:.75;-khtml-user-select:none;-o-user-select:none;-moz-user-select:none;-moz-user-focus:ignore;-moz-user-input:disabled;}div.mcdropdownDisabled input{cursor:default;}div.mcdropdownDisabled a:hover,div.mcdropdownDisabled a:focus{background-position:0 0;cursor:default;}ul.mcdropdown_menu{display:none;margin:0;padding:0;list-style-type:none;float:left;clear:both;z-index:10000;-khtml-user-select:none;-o-user-select:none;-moz-user-select:none;-moz-user-focus:ignore;-moz-user-input:disabled;}ul.mcdropdown_menu ul{display:none;font:11px Arial,Helvetica,sans-serif;}ul.mcdropdown_menu ul{position:absolute;list-style-type:none;margin:0;margin-left:30px;padding:0;z-index:10000;}ul.mcdropdown_menu ul li{margin:0;min-width:150px;_width:150px;}ul.mcdropdown_menu{height:auto;background-color:#e1e0e0;padding:5px 5px;font:11px Arial,Helvetica,sans-serif;}ul.mcdropdown_menu li{padding:2px 20px 2px 6px;}ul.mcdropdown_menu li.mc_root{cursor:pointer;white-space:nowrap;color:#666;border-top:1px solid #fff;padding:2px 20px 2px 6px;margin:0 10px;}ul.mcdropdown_menu>li.mc_endcol{border-bottom:1px solid #fff;}ul.mcdropdown_menu li.mc_hover{background-color:#ccc!important;}ul.mcdropdown_menu>li:hover{border-top:1px solid #999;background-color:#999!important;color:#fff;}ul.mcdropdown_menu>li:hover.mc_endcol{border-bottom:1px solid #999;}ul.mcdropdown_menu>li:hover+li:not(.mc_firstrow){border-top:1px solid #999;}ul.mcdropdown_menu li.mc_parent{padding-right:20px!important;background:url(../images/mcdropdown/mcdd_icon_normal.gif) no-repeat 100% 50%;}ul.mcdropdown_menu li:hover.mc_parent{background:#999 url(../images/mcdropdown/mcdd_icon_hover.gif) no-repeat 100% 50%!important;color:#fff!important;}ul.mcdropdown_menu ul{background:#f0f0f0;border:1px solid #d0d0d0;padding-bottom:10px;visibility:hidden;}ul.mcdropdown_menu ul li{background:#f0f0f0;padding-left:16px!important;border-top:1px solid #fff;color:#666;white-space:nowrap;}ul.mcdropdown_menu ul li.mc_firstrow{border-top:1px solid #f0f0f0;}ul.mcdropdown_menu ul li.mc_endcol{border-bottom:1px solid #fff;}ul.mcdropdown_menu ul li:hover{background-color:#d6d6d6;border-top:1px solid #dedede;color:#666;}ul.mcdropdown_menu ul li.mc_endcol:hover{border-bottom:1px solid #dedede;}ul.mcdropdown_menu ul li:hover+li:not(.mc_firstrow){border-top:1px solid #dedede;}div.mcdropdown_shadow{display:none;position:absolute;margin:3px 0 0 3px;background:#000;filter:alpha(opacity=33);}html>body div.mcdropdown_shadow{margin:5px 0 0 5px;padding:5px 0 0 5px;background:transparent url(../images/mcdropdown/shadow.png) right bottom no-repeat!important;filter:none;}ul.mcdropdown_autocomplete{display:block;position:absolute;height:auto;max-height:210px;overflow-x:hidden;overflow-y:auto;clear:both;padding:5px 10px;background-color:#e1e0e0;z-index:10000;margin:0;list-style-type:none;width:392px;font:11px Arial,Helvetica,sans-serif;}ul.mcdropdown_autocomplete ul{display:none;list-style-type:none;margin:0;padding:0;}ul.mcdropdown_autocomplete ul li{margin:0;}ul.mcdropdown_autocomplete li{display:block;font:11px Arial,Helvetica,sans-serif;cursor:pointer;white-space:nowrap;color:#666;border-top:1px solid #fff;padding:2px 26px 2px 6px;}ul.mcdropdown_autocomplete li.mc_endcol{border-bottom:1px solid #fff;}ul.mcdropdown_autocomplete li.mc_parent{padding-right:20px!important;background:url(../images/mcdropdown/mcdd_icon_normal.gif) no-repeat 100% 50%;}ul.mcdropdown_autocomplete li.mc_hover{border-top:1px solid #999;background-color:#999!important;color:#fff;}ul.mcdropdown_autocomplete li.mc_hover_parent{background:#999 url(../images/mcdropdown/mcdd_icon_hover.gif) no-repeat 100% 50%!important;color:#fff!important;} \ No newline at end of file
diff --git a/src/main/webapp/images/mcdropdown/mcdd_icon_hover.gif b/src/main/webapp/images/mcdropdown/mcdd_icon_hover.gif
new file mode 100644
index 0000000..468f85b
--- /dev/null
+++ b/src/main/webapp/images/mcdropdown/mcdd_icon_hover.gif
Binary files differ
diff --git a/src/main/webapp/images/mcdropdown/mcdd_icon_normal.gif b/src/main/webapp/images/mcdropdown/mcdd_icon_normal.gif
new file mode 100644
index 0000000..8e1d43b
--- /dev/null
+++ b/src/main/webapp/images/mcdropdown/mcdd_icon_normal.gif
Binary files differ
diff --git a/src/main/webapp/images/mcdropdown/mcdd_select_button_sprite.gif b/src/main/webapp/images/mcdropdown/mcdd_select_button_sprite.gif
new file mode 100644
index 0000000..3412dbc
--- /dev/null
+++ b/src/main/webapp/images/mcdropdown/mcdd_select_button_sprite.gif
Binary files differ
diff --git a/src/main/webapp/images/mcdropdown/shadow.png b/src/main/webapp/images/mcdropdown/shadow.png
new file mode 100644
index 0000000..64e7dc6
--- /dev/null
+++ b/src/main/webapp/images/mcdropdown/shadow.png
Binary files differ
diff --git a/src/main/webapp/js/jquery.bgiframe.js b/src/main/webapp/js/jquery.bgiframe.js
new file mode 100644
index 0000000..3a01f6e
--- /dev/null
+++ b/src/main/webapp/js/jquery.bgiframe.js
@@ -0,0 +1,100 @@
+/* Copyright (c) 2006 Brandon Aaron (http://brandonaaron.net)
+ * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
+ * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
+ *
+ * $LastChangedDate: 2007-07-21 18:44:59 -0500 (Sat, 21 Jul 2007) $
+ * $Rev: 2446 $
+ *
+ * Version 2.1.1
+ */
+
+(function($){
+
+/**
+ * The bgiframe is chainable and applies the iframe hack to get
+ * around zIndex issues in IE6. It will only apply itself in IE6
+ * and adds a class to the iframe called 'bgiframe'. The iframe
+ * is appeneded as the first child of the matched element(s)
+ * with a tabIndex and zIndex of -1.
+ *
+ * By default the plugin will take borders, sized with pixel units,
+ * into account. If a different unit is used for the border's width,
+ * then you will need to use the top and left settings as explained below.
+ *
+ * NOTICE: This plugin has been reported to cause perfromance problems
+ * when used on elements that change properties (like width, height and
+ * opacity) a lot in IE6. Most of these problems have been caused by
+ * the expressions used to calculate the elements width, height and
+ * borders. Some have reported it is due to the opacity filter. All
+ * these settings can be changed if needed as explained below.
+ *
+ * @example $('div').bgiframe();
+ * @before <div><p>Paragraph</p></div>
+ * @result <div><iframe class="bgiframe".../><p>Paragraph</p></div>
+ *
+ * @param Map settings Optional settings to configure the iframe.
+ * @option String|Number top The iframe must be offset to the top
+ * by the width of the top border. This should be a negative
+ * number representing the border-top-width. If a number is
+ * is used here, pixels will be assumed. Otherwise, be sure
+ * to specify a unit. An expression could also be used.
+ * By default the value is "auto" which will use an expression
+ * to get the border-top-width if it is in pixels.
+ * @option String|Number left The iframe must be offset to the left
+ * by the width of the left border. This should be a negative
+ * number representing the border-left-width. If a number is
+ * is used here, pixels will be assumed. Otherwise, be sure
+ * to specify a unit. An expression could also be used.
+ * By default the value is "auto" which will use an expression
+ * to get the border-left-width if it is in pixels.
+ * @option String|Number width This is the width of the iframe. If
+ * a number is used here, pixels will be assume. Otherwise, be sure
+ * to specify a unit. An experssion could also be used.
+ * By default the value is "auto" which will use an experssion
+ * to get the offsetWidth.
+ * @option String|Number height This is the height of the iframe. If
+ * a number is used here, pixels will be assume. Otherwise, be sure
+ * to specify a unit. An experssion could also be used.
+ * By default the value is "auto" which will use an experssion
+ * to get the offsetHeight.
+ * @option Boolean opacity This is a boolean representing whether or not
+ * to use opacity. If set to true, the opacity of 0 is applied. If
+ * set to false, the opacity filter is not applied. Default: true.
+ * @option String src This setting is provided so that one could change
+ * the src of the iframe to whatever they need.
+ * Default: "javascript:false;"
+ *
+ * @name bgiframe
+ * @type jQuery
+ * @cat Plugins/bgiframe
+ * @author Brandon Aaron (brandon.aaron@gmail.com || http://brandonaaron.net)
+ */
+$.fn.bgIframe = $.fn.bgiframe = function(s) {
+ // This is only for IE6
+ if ( $.browser.msie && /6.0/.test(navigator.userAgent) ) {
+ s = $.extend({
+ top : 'auto', // auto == .currentStyle.borderTopWidth
+ left : 'auto', // auto == .currentStyle.borderLeftWidth
+ width : 'auto', // auto == offsetWidth
+ height : 'auto', // auto == offsetHeight
+ opacity : true,
+ src : 'javascript:false;'
+ }, s || {});
+ var prop = function(n){return n&&n.constructor==Number?n+'px':n;},
+ html = '<iframe class="bgiframe"frameborder="0"tabindex="-1"src="'+s.src+'"'+
+ 'style="display:block;position:absolute;z-index:-1;'+
+ (s.opacity !== false?'filter:Alpha(Opacity=\'0\');':'')+
+ 'top:'+(s.top=='auto'?'expression(((parseInt(this.parentNode.currentStyle.borderTopWidth)||0)*-1)+\'px\')':prop(s.top))+';'+
+ 'left:'+(s.left=='auto'?'expression(((parseInt(this.parentNode.currentStyle.borderLeftWidth)||0)*-1)+\'px\')':prop(s.left))+';'+
+ 'width:'+(s.width=='auto'?'expression(this.parentNode.offsetWidth+\'px\')':prop(s.width))+';'+
+ 'height:'+(s.height=='auto'?'expression(this.parentNode.offsetHeight+\'px\')':prop(s.height))+';'+
+ '"/>';
+ return this.each(function() {
+ if ( $('> iframe.bgiframe', this).length == 0 )
+ this.insertBefore( document.createElement(html), this.firstChild );
+ });
+ }
+ return this;
+};
+
+})(jQuery); \ No newline at end of file
diff --git a/src/main/webapp/js/jquery.mcdropdown.js b/src/main/webapp/js/jquery.mcdropdown.js
new file mode 100644
index 0000000..a99c66b
--- /dev/null
+++ b/src/main/webapp/js/jquery.mcdropdown.js
@@ -0,0 +1,1139 @@
+(function ($){
+/*!
+ * mcDropdown jQuery Plug-in
+ *
+ * Copyright 2011 Giva, Inc. (http://www.givainc.com/labs/)
+ *
+ * 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.
+ *
+ * Date: 2011-07-25
+ * Rev: 1.3.1
+ */
+ $.fn.mcDropdown = function(list, options) {
+ // track the dropdown object
+ var dd;
+
+ // create a dropdown for each match
+ this.each(function() {
+ dd = $.data(this, "mcDropdown");
+
+ // we're already a dropdown, return a reference to myself
+ if( dd ) return false;
+
+ new $.mcDropDownMenu(this, list, options);
+ });
+
+ // return either the dropdown object or the jQuery object reference
+ return dd || this;
+ };
+
+ // set default options
+ $.mcDropdown = {
+ version: "1.3.1",
+ setDefaults: function(options){
+ $.extend(defaults, options);
+ }
+ };
+
+ // set the defaults
+ var defaults = {
+ minRows: 8 // specify the minimum rows before creating a new column
+ , maxRows: 25 // specify the maximum rows in a column
+ , targetColumnSize: 2 // specify the default target column size (it'll attempt to create this many columns by default, unless the min/max row rules are not being met)
+ , openFx: "slideDown" // the fx to use for showing the root menu
+ , openSpeed: 250 // the speed of the openFx
+ , closeFx: "slideUp" // the fx to use for hiding the root menu
+ , closeSpeed: 250 // the speed of the closeFx
+ , hoverOverDelay: 200 // the delay before opening a submenu
+ , hoverOutDelay: 0 // the delay before closing a submenu
+ , showFx: "show" // the fx to use when showing a submenu
+ , showSpeed: 0 // the speed of the showFx
+ , hideFx: "hide" // the fx to use when closing a submenu
+ , hideSpeed: 0 // the speed of the hideFx
+ , dropShadow: true // determine whether drop shadows should be shown on the submenus
+ , autoHeight: true // always uses the lineHeight options (much faster than calculating height)
+ , lineHeight: 19 // the base height of each list item (li) this is normally calculated automatically, but in some cases the value can't be determined and you'll need to set it manually
+ , screenPadding: 10 // the padding to use around the border of the screen -- this is used to make sure items stay on the screen
+ , allowParentSelect: false // determines if parent items are allowed to be selected (by default only end nodes can be selected)
+ , delim: ":" // the delimited to use when showing the display string
+ , showACOnEmptyFocus: false // show the autocomplete box on focus when input is empty
+ , valueAttr: "rel" // the attribute that contains the value to use in the hidden field
+ , click: null // callback that occurs when the user clicks on a menu item
+ , select: null // callback that occurs when a value is selected
+ , init: null // callback that occurs when the control is fully initialized
+ };
+
+ // check to see if the browser is IE6
+ var isIE6 = ($.browser.version && $.browser.version <= 6);
+
+ $.mcDropDownMenu = function(el, list, options){
+ var $self, thismenu = this, $list, $divInput, settings, typedText = "", matchesCache, oldCache, $keylist, $keylistiframe, bInput, bDisabled = false;
+
+ // create a reference to the dropdown
+ $self = $(el);
+
+ // is the field and input element
+ bInput = $self.is(":input");
+
+ // get the settings for this instance
+ settings = $.extend({}, defaults, options);
+
+ // set the default click behavior
+ if( settings.click == null ) {
+ settings.click = function (e, dropdown, settings){
+ if( this.attr(settings.valueAttr) ){
+ dropdown.setValue(this.attr(settings.valueAttr));
+ } else {
+ dropdown.setValue($(this.parents("li")[0]).attr(settings.valueAttr));
+ }
+ };
+ }
+
+ // attach window behaviors
+ $(document)
+ // Bind a click event to hide all visible menus when the document is clicked
+ .bind("click", function(e){
+ // get the target that was clicked
+ var $target = $(e.target);
+ var $ul = $target.parents().filter(function (){ return this === $list[0] || (!!$keylist && $keylist[0] === this); });
+ // check to make sure the clicked element was inside the list
+ if( $ul.length ){
+ var bIsParent = $target.is(".mc_parent");
+
+ // if we've clicked a parent item in the autocomplete box, we must adjust the current value
+ if( bIsParent && $keylist && $ul[0] === $keylist[0] ){
+ updateValue($target.find("> ul > li:first"), false);
+ e.stopPropagation();
+ return false;
+ }
+ // check to see if the user can click on parent items
+ else if( !settings.allowParentSelect && bIsParent ) return false;
+
+ // make sure to hide the parent branch if we're not the root
+ if( $target.not(".mc_root") ) hideBranch.apply($target.parent().parent()[0], [e]);
+
+ if( settings.click != null && settings.click.apply($target, [e, thismenu, settings]) == false ){
+ return false;
+ }
+ }
+
+ // close the menu
+ thismenu.closeMenu();
+ });
+
+ // store a reference to the list, if it's not already a jQuery object make it one
+ $list = (((typeof list == "object") && !!list.jquery)) ? list : $(list);
+
+ // we need to calculate the visual width for each nested list
+ $list
+ // move list to body -- this allows us to always calculate the correct position & width of the elements
+ .appendTo("body")
+ // move the list way off screen
+ .css({position: "absolute", top: -10000, left: -10000})
+ // find all the ul tags
+ .find("ul")
+ // add the root ul tag to the array
+ .andSelf()
+ // make all the nodes visible
+ .css("display", "block")
+ // loop through each node
+ .each(function (){
+ var $el = $(this);
+ // calculate the width of the element -- using clientWidth is 2x as fast as width()
+ $el.data("width", $el[0].clientWidth);
+ })
+ // now that we've gotten the widths, hide all the lists and move them to x:0, y:0
+ .css({top: 0, left: 0, display: "none"});
+
+ // mark the root children items
+ $list.find("> li").addClass("mc_root");
+ // add parent class
+ $("li > ul", $list).parent().addClass("mc_parent");
+
+ // create the div to wrap everything in
+ $divInput = $('<div class="mcdropdown"><a href="#" tabindex="-1"></a><input type="hidden" name="' + (el.name || el.id) + '" id="' + (el.id || el.name) + '" /></div>')
+ .appendTo($('<div style="position: relative;"></div>'))
+ .parent();
+
+ // get a reference to the input element and remove it from the DOM
+ var $input = $self.replaceWith($divInput).attr({id: "", name: ""});
+ // get a reference to the hidden form field
+ var $hidden = $divInput.find(":input");
+
+ // put the input element back in the div.mcdropdown layer
+ $divInput = $divInput.find(".mcdropdown").prepend($input);
+
+ // make a visible copy of the element so we can get the correct sizes, then delete it
+ var $divInputClone = $divInput.clone().css({position: "absolute", top: -9999999, left: -999999, visibility: "visible"}).show().appendTo("body");
+ var di = {width: $divInputClone.width() - $("a", $divInputClone).width(), height: $divInputClone.outerHeight()}
+ $divInputClone.remove();
+
+ // store a reference to this link select
+ $.data($hidden[0], "mcDropdown", thismenu);
+
+ // update the height of the outer relative div, this allows us to
+ // correctly anchor the dropdown
+ $divInput.parent().height(di.height);
+
+ // safari will not get the correct width until after everything has rendered
+ if( $.browser.safari ){
+ setTimeout(function (){
+ $self
+ .width($divInput.width() - $("a", $divInput).width());
+ }, 100);
+ }
+
+ // adjust the width of the new input element
+ $self
+ .width(di.width)
+ // make sure we only attach the next events if we're in input element
+ .filter(":input")
+ // turn autocomplete off
+ .attr("autocomplete", "off")
+ // add key stroke bindings (IE6 requires keydown)
+ .bind("keypress", checkKeypress)
+ // prevent user from selecting text
+ .bind("mousedown", function (e){ $(this).triggerHandler("focus"); e.stopPropagation(); return false; })
+ // disable context menu
+ .bind("contextmenu", function (){ return false; })
+ // select the text when the cursor is placed in the field
+ .bind("focus", onFocus)
+ // when the user leaves the text field
+ .bind("blur", onBlur);
+
+ // IE6 doesn't register certain keypress events, so we must catch them during the keydown event
+ if( $.browser.msie || $.browser.safari) $self.bind("keydown", function (e){
+ // check to see if a key was pressed that IE6 doesn't trigger a keypress event for
+ if( ",8,9,37,38,39,40,".indexOf("," + e.keyCode + ",") > -1 ) return checkKeypress(e);
+ });
+
+ // attach a click event to the anchor
+ $("a", $divInput).bind("click", function (e){
+ // if disabled, skip processing
+ if( bDisabled ) return false;
+ thismenu.openMenu(e);
+ return false;
+ });
+
+ // set the value of the field
+ this.setValue = function (value, skipCallback){
+ // update the hidden value
+ $hidden.val(value);
+ // get the display name
+ var name = displayString(value);
+
+ // run the select callback (some keyboard entry methods will manage this callback manually)
+ if( settings.select != null && skipCallback != true ) settings.select.apply(thismenu, [value, name]);
+
+ // update the display value and return the jQuery object
+ return $self[bInput ? "val" : "text"](name);
+ };
+
+ // set the default value (but don't run callback)
+ if( bInput ) this.setValue($self[0].defaultValue, true);
+
+ // get the value of the field (returns array)
+ this.getValue = function (value){
+ return [$hidden.val(), $self[bInput ? "val" : "text"]()];
+ };
+
+ // open the menu programmatically
+ this.openMenu = function (e){
+ // if the menu is open, kill processing
+ if( $list.is(":visible") ){
+ // on a mouse click, close the menu, otherwise just cancel
+ return (!!e) ? thismenu.closeMenu() : false;
+ }
+
+ function open(){
+ // columnize the root list
+ columnizeList($list).hide();
+ // add the bindings to the menu
+ addBindings($list);
+
+ // anchor the menu relative parent
+ anchorTo($divInput.parent(), $list, true);
+
+ // remove existing hover classes, which might exist from keyboard entry
+ $list.find(".mc_hover").removeClass("mc_hover");
+
+ // show the menu
+ $list[settings.openFx](settings.openSpeed, function (){
+ // scroll the list into view
+ scrollToView($list);
+ });
+
+ // if the bgIframe exists, use the plug-in
+ if( isIE6 && !!$.fn.bgIframe ) $list.bgIframe();
+ }
+
+ // if this is triggered via an event, just open the menu
+ if( e ) open();
+ // otherwise we need to open the menu asynchronously to avoid collision with $(document).click event
+ else setTimeout(open, 1);
+ };
+
+ // close the menu programmatically
+ this.closeMenu = function (e){
+ // hide any open menus
+ $list.find("ul:visible").parent().each(function (){
+ hideBranch.apply(this);
+ });
+
+ // remove the bindings
+ removeBindings($list);
+
+ // close the menu
+ $list[settings.closeFx](settings.closeSpeed);
+ };
+
+ // place focus in the input box
+ this.focus = function (){
+ $self.focus();
+ };
+
+ // disable the element
+ this.disable = function (status){
+ // change the disabled status
+ bDisabled = !!status;
+
+ $divInput[bDisabled ? "addClass" : "removeClass"]("mcdropdownDisabled");
+ $input.attr("disabled", bDisabled);
+ };
+
+ function getNodeText($el){
+ var nodeContent;
+ var nContents = $el.contents().filter(function() {
+ // remove empty text nodes and comments
+ return (this.nodeType == 1) || (this.nodeType == 3 && $.trim(this.nodeValue).length>0);
+ });
+ // return either an empty string or the node's value
+ if (nContents[0] && nContents[0].nodeType == 3) {
+ // Text node : take it's value
+ nodeContent = nContents[0].nodeValue;
+ } else if (nContents[0] && nContents[0].nodeType == 1) {
+ // Element node : take the contents
+ nodeContent = $(nContents[0]).text();
+ } else {
+ nodeContent = "";
+ }
+ return $.trim(nodeContent);
+ };
+
+ function getTreePath($li){
+ if( $li.length == 0 ) return [];
+
+ var name = [getNodeText($li)];
+ // loop through the parents and get the value
+ $li.parents().each(function (){
+ var $el = $(this);
+ // break when we get to the main list element
+ if( this === $list[0] ) return false;
+ else if( $el.is("li") ) name.push(getNodeText($el));
+ });
+
+ // return the display name
+ return name.reverse();
+ };
+
+ function displayValue(value){
+ // return the path as an array
+ return getTreePath(getListItem(value));
+ };
+
+ function displayString(value){
+ // return the display name
+ return displayValue(value).join(settings.delim);
+ };
+
+ function parseTree($selector){
+ var s = [], level = (arguments.length > 1) ? ++arguments[1] : 1;
+
+ // loop through all the children and store information about the tree
+ $("> li", $selector).each(
+ function (){
+ // get a reference to the current object
+ var $self = $(this);
+
+ // look for a ul tag as a direct child
+ var $ul = $("> ul", this);
+
+ // push a reference to the element to the tree array
+ s.push({
+ // get the name of the node
+ name: getNodeText($self)
+ // store a reference to the current element
+ , element: this
+ // parse and store any children items
+ , children: ($ul.length) ? parseTree($ul, level) : []
+ });
+
+ }
+ );
+
+ return s;
+ };
+
+ function addBindings(el){
+ removeBindings(el);
+ $("> li", el)
+ .bind("mouseover", hoverOver)
+ .bind("mouseout", hoverOut);
+ };
+
+ function removeBindings(el){
+ $("> li", el)
+ .unbind("mouseover", hoverOver)
+ .unbind("mouseout", hoverOut);
+ };
+
+ // scroll the current element into view
+ function scrollToView($el){
+ // get the current position
+ var p = position($el, true);
+ // get the screen dimensions
+ var sd = getScreenDimensions();
+
+ // if we're hidden off the bottom of the page, move up
+ if( p.bottom > sd.y ){
+ $("html,body").animate({"scrollTop": "+=" + ((p.bottom - sd.y) + settings.screenPadding) + "px" })
+ }
+ };
+
+ function hoverOver(e){
+ var self = this;
+ var timer = $.data(self, "timer");
+
+ // if the timer exists, clear it
+ if( !isNaN(timer) ) clearTimeout(timer);
+
+ // if IE6, add the hover class
+ $(this).addClass("mc_hover");
+
+ // show the branch
+ $.data(self, "timer", setTimeout(function(){
+ showBranch.apply(self);
+ }, settings.hoverOverDelay)
+ );
+ };
+
+ function hoverOut(e){
+ var self = this;
+ var timer = $.data(self, "timer");
+
+ // if the timer exists, clear it
+ if( !isNaN(timer) ) clearTimeout(timer);
+
+ // if IE6, remove the hover class
+ $(this).removeClass("mc_hover");
+
+ // hide the branch
+ $.data(self, "timer", setTimeout(function(){
+ var $li = $(self);
+ setTimeout(function (){
+ // if no children selected, we must close the parent menus
+ if( $li.parent().find("> li.mc_hover").length == 0 ){
+ $li.parents("li").each(function (){
+ var self = this;
+ clearTimeout($.data(self, "timer"));
+ hideBranch.apply(self);
+ // check to see if we've hovered over a parent item
+ if( $(this).siblings().filter(".mc_hover").length > 0 ) return false;
+ });
+ }
+
+ }, settings.hoverOverDelay);
+
+ hideBranch.apply(self);
+ }, settings.hoverOutDelay)
+ );
+
+ // this will stop flickering in IE6, but it leaves mc_hover classes behind
+ if( isIE6 ) e.stopPropagation();
+ };
+
+ function getShadow(depth){
+ var shadows = $self.data("shadows");
+
+ // if the shadows don't exist, create an object to track them
+ if( !shadows )
+ shadows = {};
+
+ // if the shadow doesn't exist, create it
+ if( !shadows[depth] ){
+ // create shadow
+ shadows[depth] = $('<div class="mcdropdown_shadow"></div>').appendTo('body');
+ // if the bgIframe exists, use the plug-in
+ if( !!$.fn.bgIframe ) shadows[depth].bgIframe();
+ // update the shadows cache
+ $self.data("shadows", shadows);
+ }
+
+ return shadows[depth];
+ };
+
+ function showBranch(){
+ var self = this;
+ // the child menu
+ var $ul = $("> ul", this);
+
+ // if the menu is already visible or there is no submenu, cancel
+ if( $ul.is(":visible") || ($ul.length == 0) ) return false;
+
+ // hide any visible sibling menus
+ $(this).parent().find('> li ul:visible').not($ul).parent().each(function(){
+ hideBranch.apply(this);
+ });
+
+ // columnize the list
+ columnizeList($ul);
+
+ // add new bindings
+ addBindings($ul);
+
+ var depth = $ul.parents("ul").length;
+
+ // get the screen dimensions
+ var sd = getScreenDimensions();
+
+ // get the coordinates for the menu item
+ var li_coords = position($(this));
+
+ // move the menu to the correct position and show the menu || ((depth)*2)
+ $ul.css({top: li_coords.bottom, left: li_coords.marginLeft/*, zIndex: settings.baseZIndex + ((depth)*2)*/}).show();
+
+ // get the bottom of the menu
+ var menuBottom = $ul.outerHeight() + $ul.offset().top;
+
+ // if we're hidden off the bottom of the page, move up
+ if( menuBottom > sd.y ){
+ // adjust the menu by subtracting the bottom edge by the screen offset
+ $ul.css("top", li_coords.bottom - (menuBottom - sd.y) - settings.screenPadding);
+ }
+
+ var showShadow = function (){
+ // if using drop shadows, then show them
+ if( settings.dropShadow ){
+ // get a reference to the current shadow
+ var $shadow = getShadow(depth);
+ // get the position of the parent element
+ var pos = position($ul);
+
+ // move the shadow to the correct visual & DOM position
+ $shadow.css({
+ top: pos.top + pos.marginTop
+ , left: pos.left + pos.marginLeft
+ , width: pos.width
+ , height: pos.height
+ /*, zIndex: settings.baseZIndex + ((2*depth)-1)*/
+ }).insertAfter($ul).show();
+
+ // store a reference to the shadow so we can hide it
+ $.data(self, "shadow", $shadow);
+ }
+ }
+
+ // columnize the list and then show it using the defined effect
+ // if the menu has a zero delay, just open it and then draw the
+ // shadow, otherwise show the effect and the draw the shadow
+ // after you're done.
+ if( settings.showSpeed <= 0 ){
+ showShadow();
+ } else {
+ $ul.hide()[settings.showFx](settings.showSpeed, showShadow);
+ }
+ };
+
+ function hideBranch(){
+ var $ul = $("> ul", this);
+ // if the menu is already visible or there is no submenu, cancel
+ if( $ul.is(":hidden") || ($ul.length == 0) ) return false;
+
+ // if using drop shadows, then hide
+ if( settings.dropShadow && $.data(this, "shadow") ) $.data(this, "shadow").hide();
+
+ // if we're IE6, we need to set the visiblity to "hidden" so child
+ // menus are correctly hidden and remove the .mc_hover class due to
+ // the e.stopPropagation() call in the hoverOut() call
+ if( isIE6 )
+ $ul.css("visibility", "hidden").parent().removeClass("mc_hover");
+
+ // hide the menu
+ $ul.stop()[settings.hideFx](settings.hideSpeed);
+ };
+
+ function position($el, bUseOffset){
+ var bHidden = false;
+ // if the element is hidden we must make it visible to the DOM to get
+ if ($el.is(":hidden")) {
+ bHidden = !!$el.css("visibility", "hidden").show();
+ }
+
+ var pos = $.extend($el[bUseOffset === true ? "offset" : "position"](),{
+ width: $el.outerWidth()
+ , height: $el.outerHeight()
+ , marginLeft: parseInt($.curCSS($el[0], "marginLeft", true), 10) || 0
+ , marginRight: parseInt($.curCSS($el[0], "marginRight", true), 10) || 0
+ , marginTop: parseInt($.curCSS($el[0], "marginTop", true), 10) || 0
+ , marginBottom: parseInt($.curCSS($el[0], "marginBottom", true), 10) || 0
+ });
+
+ if( pos.marginTop < 0 ) pos.top += pos.marginTop;
+ if( pos.marginLeft < 0 ) pos.left += pos.marginLeft;
+
+ pos["bottom"] = pos.top + pos.height;
+ pos["right"] = pos.left + pos.width;
+
+ // hide the element again
+ if( bHidden ) $el.hide().css("visibility", "visible");
+
+ return pos;
+ };
+
+ function anchorTo($anchor, $target, bUseOffset){
+ var pos = position($anchor, bUseOffset);
+
+ $target.css({
+ position: "absolute"
+ , top: pos.bottom
+ , left: pos.left
+ });
+
+ /*
+ * we need to return the top edge of the core drop down menu, because
+ * the top:0 starts at this point when repositioning items absolutely
+ * this means we have to offset everything by the offset of the top menu
+ */
+
+ return pos.bottom;
+ };
+
+ function getScreenDimensions(){
+ var d = {
+ scrollLeft: $(window).scrollLeft()
+ , scrollTop: $(window).scrollTop()
+ , width: $(window).width() // changed from innerWidth
+ , height: $(window).height() // changed from innerHeight
+ };
+
+ // calculate the correct x/y positions
+ d.x = d.scrollLeft + d.width;
+ d.y = d.scrollTop + d.height;
+
+ return d;
+ };
+
+ function getPadding(el, name){
+ var torl = name == 'height' ? 'Top' : 'Left', // top or left
+ borr = name == 'height' ? 'Bottom' : 'Right'; // bottom or right
+
+ return (
+ // we add "0" to each string to make sure parseInt() returns a number
+ parseInt("0"+$.curCSS(el, "border"+torl+"Width", true), 10)
+ + parseInt("0"+$.curCSS(el, "border"+borr+"Width", true), 10)
+ + parseInt("0"+$.curCSS(el, "padding"+torl, true), 10)
+ + parseInt("0"+$.curCSS(el, "padding"+borr, true), 10)
+ + parseInt("0"+$.curCSS(el, "margin"+torl, true), 10)
+ + parseInt("0"+$.curCSS(el, "margin"+borr, true), 10)
+ );
+ };
+
+ function getListDimensions($el, cols){
+ if( !$el.data("dimensions") ){
+ // get the width of the dropdown menu
+ var ddWidth = $divInput.outerWidth();
+ // if showing the root item, then try to make sure the width of the menu is sized to the drop down menu
+ var width = ( ($el === $list) && ($el.data("width") * cols < ddWidth) ) ? Math.floor(ddWidth/cols) : $el.data("width");
+
+ $el.data("dimensions", {
+ // get the original width of the list item
+ column: width
+ // subtract the padding from the first list item from the width to get the width of the items
+ , item: width - getPadding($el.children().eq(0)[0], "width")
+ // get the original height
+ , height: $el.height()
+ });
+ }
+
+ return $el.data("dimensions");
+ };
+
+ function getHeight($el){
+ // skip height calculation and use lineHeight
+ if( settings.autoHeight === false ) return settings.lineHeight;
+ // if we haven't cached our height, do so now
+ if( !$el.data("height") ) $el.data("height", $el.outerHeight());
+
+ // return the cached value
+ return $el.data("height");
+ };
+
+ function columnizeList($el){
+ // get the children items
+ var $children = $el.find("> li");
+ // get the total number of items
+ var items = $children.length;
+
+ // calculate how many columns we think we should have based on the max rows
+ var calculatedCols = Math.ceil(items/settings.maxRows);
+ // get the number of columns, don't columnize if we don't have enough rows
+ // if the height of the column is bigger than the screen, we automatically try
+ // moving to a new column
+ var cols = !!arguments[1] ? arguments[1] : ( items <= settings.minRows ) ? 1 : (calculatedCols > settings.targetColumnSize) ? calculatedCols : settings.targetColumnSize;
+ // get the dimension of this element
+ var widths = getListDimensions($el, cols);
+ var prevColumn = 0;
+ var columnHeight = 0;
+ var maxColumnHeight = 0;
+ var maxRows = Math.ceil(items/cols);
+
+ // get the width of the parent item
+ var parentLIWidth = $el.parent("li").width();
+
+ // we need to draw the list element, but hide it so we can correctly calculate it's information
+ $el.css({"visibility": "hidden", "display": "block"});
+
+ // loop through each child item
+ $children.each(function (i){
+ var currentItem = i+1;
+ var nextItemColumn = Math.floor((currentItem/items) * cols);
+ // calculate the column we're in
+ var column = Math.floor((i/items) * cols);
+ // reference the current item
+ var $li = $(this);
+ // variable to track margin-top
+ var marginTop;
+
+ // if we're in the same column
+ if( prevColumn != column ){
+ // move to the top of the next column
+ marginTop = (columnHeight+1) * -1;
+ // reset column height
+ columnHeight = 0;
+ // if we're in a new column
+ } else {
+ marginTop = 0;
+ }
+
+ // increase the column height based on it's current height (calculate this before adding classes)
+ columnHeight += (getHeight($li) || settings.lineHeight);
+
+ // update the css settings
+ $li.css({
+ "marginLeft": (widths.column * column)
+ , "marginTop": marginTop
+ , "width": widths.item
+ })
+ [((nextItemColumn > column) || (currentItem == items)) ? "addClass" : "removeClass"]("mc_endcol")
+ [(marginTop != 0) ? "addClass" : "removeClass"]("mc_firstrow")
+ ;
+ // get the height of the longest column
+ if( columnHeight > maxColumnHeight ) maxColumnHeight = columnHeight;
+
+ // update the previous column
+ prevColumn = column;
+ });
+
+ // if the menu is too tall to fit on the screen, try adding another column
+ if( ($el !== $list) && (maxColumnHeight + (settings.screenPadding*2) >= getScreenDimensions().height) ){
+ return columnizeList($el, cols+1);
+ }
+
+ /*
+ * set the height of the list to the max column height. this fixes
+ * display problems in FF when the last column is not full.
+ *
+ * we also need to set the visiblity to "visible" to make sure that
+ * the element will show up
+ */
+ $el.css("visibility", "visible").height(maxColumnHeight);
+
+ return $el;
+ };
+
+ function getListItem(value){
+ return $list.find("li[" + settings.valueAttr + "='"+ value +"']");
+ };
+
+ function getCurrentListItem(){
+ return getListItem($hidden.val());
+ };
+
+ function onFocus(e){
+ var $current = getCurrentListItem();
+ var value = $self.val().toLowerCase();
+ var treePath = value.toLowerCase().split(settings.delim);
+ var currentNode = treePath.pop();
+ var lastDelim = value.lastIndexOf(settings.delim) + 1;
+
+ // reset the typed text
+ typedText = treePath.join(settings.delim) + (treePath.length > 0 ? settings.delim : "");
+
+ // we need to set the selection asynchronously so that when user TABs to field the pre-select isn't overwritten
+ setTimeout(function (){
+ // preselect the last child node
+ setSelection($self[0], lastDelim, lastDelim+currentNode.length);
+ }, 0);
+
+ // create the keyboard hint list
+ if( !$keylist ){
+ $keylist = $('<ul class="mcdropdown_autocomplete"></ul>').appendTo("body");
+ // if IE6 we need an iframe to hide the scrolling list
+ if( isIE6 && !!$.fn.bgIframe ) $keylistiframe = $('<div></div>').bgIframe().appendTo("body");
+ }
+
+ // should we show matches?
+ var hideResults = !(settings.showACOnEmptyFocus && (typedText.length == 0));
+
+ // get the siblings for the current item
+ var $siblings = ($current.length == 0 || $current.hasClass("mc_root")) ? $list.find("> li") : $current.parent().find("> li");
+ // show all matches
+ showMatches($siblings, hideResults);
+ };
+
+ var iBlurTimeout = null;
+ function onBlur(e){
+ // only run the last blur event
+ if( iBlurTimeout ) clearTimeout(iBlurTimeout);
+ // we may need to cancel this blur event, so we run it asynchronously
+ iBlurTimeout = setTimeout(function (){
+ // get the current item
+ var $current = getCurrentListItem();
+
+ // if we must select a child item, then update to the first child we can find
+ if( !settings.allowParentSelect && $current.is(".mc_parent") ){
+ // grab the first end child item we can find for the current path
+ var value = $current.find("li:not('.mc_parent'):first").attr(settings.valueAttr);
+ // update the value
+ thismenu.setValue(value, true);
+ }
+
+ // run the select callback
+ if( settings.select != null ) settings.select.apply(thismenu, thismenu.getValue());
+
+ // hide matches
+ hideMatches();
+
+ // mark event as having run
+ iBlurTimeout = null;
+ }, 200);
+ };
+
+ function showMatches($li, hideResults){
+ var bCached = ($li === oldCache), $items = bCached ? $keylist.find("> li").removeClass("mc_hover mc_hover_parent mc_firstrow") : $li.clone().removeAttr("style").removeClass("mc_hover mc_hover_parent mc_firstrow mc_endcol").filter(":last").addClass("mc_endcol").end();
+
+ // only do the following if we've updated the cache or the list is hidden
+ if( !bCached || $keylist.is(":hidden") ){
+ // update the matches
+ $keylist.empty().append($items).width($divInput.outerWidth() - getPadding($keylist[0], "width")).css("height", "auto");
+
+ // anchor the menu relative parent
+ anchorTo($divInput.parent(), $keylist, true);
+
+ // show hover on mouseover
+ $items.hover(function (){$keylist.find("> li").removeClass("mc_hover_parent mc_hover"); $(this).addClass("mc_hover")}, function (){$(this).removeClass("mc_hover")});
+
+ // make sure the the ul's are hidden (so the li's are sized correctly)
+ $items.find("> ul").css("display", "none");
+
+ // show the list
+ $keylist.show().css("visibility", (hideResults === true) ? "hidden" : "visible");
+
+ // if we're IE6, ensure we enforce the "max-height" CSS property
+ if( isIE6 ){
+ var maxHeight = parseInt($keylist.css("max-height"), 10) || 0;
+ if( (maxHeight > 0) && (maxHeight < $keylist.outerHeight()) ) $keylist.height(maxHeight);
+
+ // anchor the iframe behind the scrollable list
+ if( !!$.fn.bgIframe ) anchorTo($divInput.parent(), $keylistiframe.css({height: $keylist.outerHeight(), width: $keylist.width()}, true).show())
+ }
+
+ // scroll the list into view
+ if( hideResults !== true ) scrollToView($keylist);
+ }
+
+ // do not show the list on screen
+ if( hideResults === true ){
+ // hide the results and move them offscreen (so it doesn't hide the cursor in FF2)
+ $keylist.css({top: "-10000px", left: "-10000px"});
+ // hiden the iframe overlay
+ if( isIE6 && !!$.fn.bgIframe ) $keylistiframe.css("display", "none");
+ }
+
+ // get the currently selected item
+ var $current = $keylist.find("li[" + settings.valueAttr + "='"+ $hidden.val() +"']");
+
+ // make sure the last match is still highlighted
+ $current.addClass("mc_hover" + ($current.is(".mc_parent")? "_parent" : ""));
+
+ // scroll the item into view
+ if( $current.length > 0 && (hideResults != true) ) scrollIntoView($current);
+
+ // update the cache
+ oldCache = matchesCache = $li;
+ };
+
+ function hideMatches(){
+ // hide the bgiframe
+ if( isIE6 && !!$.fn.bgIframe && $keylistiframe ) $keylistiframe.hide();
+ if( $keylist ) $keylist.hide();
+ };
+
+ // check the user's keypress
+ function checkKeypress(e){
+ var key = String.fromCharCode(e.keyCode || e.charCode).toLowerCase();
+ var $current = getCurrentListItem();
+ var $lis = ($current.length == 0 || $current.hasClass("mc_root")) ? $list.find("> li") : $current.parent().find("> li");
+ var treePath = typedText.split(settings.delim);
+ var currentNode = treePath.pop();
+ var compare = currentNode + key;
+ var selectedText = getSelection($self[0]).toLowerCase();
+ var value = $self.val().toLowerCase();
+
+ // if the up arrow was pressed
+ if( e.keyCode == 38 ){
+ moveMatch(-1);
+ return false;
+
+ // if the down arrow was pressed
+ } else if( e.keyCode == 40 ){
+ moveMatch(1);
+ return false;
+
+ // if the [ESC] was pressed
+ } else if( e.keyCode == 27 ){
+ // clear typedText
+ typedText = "";
+ // clear the value
+ thismenu.setValue("");
+ // show the root level
+ showMatches($list.find("> li"));
+
+ return false;
+
+ // if user pressed [DEL] or [LEFT ARROW], go remove last typed character
+ } else if( e.keyCode == 8 || e.keyCode == 37 ){
+ // if left arrow, go back to previous parent
+ compare = (e.keyCode == 37) ? "" : currentNode.substring(0, currentNode.length - 1);
+
+ // if all the text is highlighted we just came from a delete
+ if( selectedText == currentNode ){
+ currentNode = "";
+ }
+ // we're going backwards to the last parent, move backwards
+ if( treePath.length > 0 && currentNode.length == 0){
+ updateValue($current.parent().parent());
+ return false;
+ // if all the text is selected, remove everything
+ } else if( selectedText == value ){
+ typedText = "";
+ thismenu.setValue("");
+ return false;
+ }
+ // if the user pressed [ENTER], [TAB], [RIGHT ARROW] or the delimiter--go to next level
+ } else if( e.keyCode == 9 || e.keyCode == 13 || e.keyCode == 39 || key == settings.delim ){
+ // get the first child item if there is one
+ var $first = $current.find("> ul > li:first");
+
+ // update with the next child branch
+ if( $first.length > 0 ){
+ updateValue($first);
+ // leave the field
+ } else {
+ // if IE6, we must deselect the selection
+ if( $.browser.msie ) setSelection($self[0], 0, 0);
+ if( e.keyCode == 9 ){
+ // blur out of the field
+ $self.triggerHandler("blur");
+ // hide the matches
+ hideMatches();
+ // allow the tab
+ return true;
+ } else {
+ // blur out of the field
+ $self.trigger("blur");
+ // hide the matches
+ hideMatches();
+ }
+ }
+
+ return false;
+ // if all the text is highlighted then we need to delete everything
+ } else if( selectedText == value ){
+ typedText = "";
+ compare = key;
+ }
+
+ // update the match cache with all the matches
+ matchesCache = findMatches($lis, compare);
+
+ // if we have some matches, populate autofill and show matches
+ if( matchesCache.length > 0 ){
+ // update the a reference to what the user's typed
+ typedText = treePath.join(settings.delim) + (treePath.length > 0 ? settings.delim : "") + compare;
+ updateValue(matchesCache.eq(0), true);
+ } else {
+ // find the previous compare string
+ compare = compare.length ? compare.substring(0, compare.length-1) : "";
+
+ // since we have no matches, get the previous matches
+ matchesCache = findMatches($lis, compare);
+
+ // if we have some matches, show them
+ if( matchesCache.length > 0 )
+ showMatches(matchesCache);
+ // hide the matches
+ else
+ hideMatches();
+ }
+
+ // stop default behavior
+ e.preventDefault();
+
+ return false;
+ };
+
+ function moveMatch(step){
+ // find the current item in the matches cache
+ var $current = getCurrentListItem(), $next, pos = 0;
+
+ // if nothing selected, look for the item with the hover class
+ if( $current.length == 0 ) $current = matchesCache.filter(".mc_hover, .mc_hover_parent");
+ // if still nothing, grab the first item in the cache
+ if( $current.length == 0 || $keylist.is(":hidden") ){
+ // grab the first item
+ $current = matchesCache.eq(0);
+ // since nothing is selected, don't step forward/back
+ step = 0;
+ }
+
+ // find the current position of the element
+ matchesCache.each(function (i){
+ if( this === $current[0]){
+ pos = i;
+ return false;
+ }
+ });
+
+ // if no matches, cancel
+ if( !matchesCache || matchesCache.length == 0 || $current.length == 0 ) return false;
+
+ // adjust by the step count
+ pos = pos + step;
+
+ // make sure pos is in valid bounds
+ if( pos < 0 ) pos = matchesCache.length-1;
+ else if( pos >= matchesCache.length ) pos = 0;
+
+ // get the next item
+ $next = matchesCache.eq(pos);
+
+ updateValue($next, true);
+ };
+
+ function findMatches($lis, compare){
+ var matches = $([]); // $([]) = empty jquery object
+
+ $lis.each(function (){
+ // get the current list item and it's label
+ var $li = $(this), label = getNodeText($li);
+
+ // label matches what the user typed, add it to the queue
+ if( label.substring(0, compare.length).toLowerCase() == compare ){
+ // store a copy to this jQuery item
+ matches = matches.add($li);
+ }
+ });
+
+ // return the matches found
+ return matches;
+ };
+
+ function updateValue($li, keepTypedText){
+ // grab all direct children items
+ var $siblings = keepTypedText ? matchesCache : ($li.length == 0 || $li.hasClass("mc_root")) ? $list.find("> li") : $li.parent().find("> li");
+ var treePath = getTreePath($li);
+ var currentNode = treePath.pop().toLowerCase();
+
+ // update the a reference to what the user's typed
+ if( !keepTypedText ) typedText = treePath.join(settings.delim).toLowerCase() + (treePath.length > 0 ? settings.delim : "");
+
+ // update form field and display with the updated value
+ thismenu.setValue($li.attr(settings.valueAttr), true);
+
+ // pre-select the last node
+ setSelection($self[0], typedText.length, currentNode.length+typedText.length);
+
+ // remove any currently selected items
+ $siblings.filter(".mc_hover,.mc_hover_parent").removeClass("mc_hover mc_hover_parent");
+ // add the hover class
+ $li.addClass("mc_hover" + ($li.is(".mc_parent")? "_parent" : ""));
+
+ // show all the matches
+ showMatches($siblings);
+ };
+
+ // get the text currently selected by the user in a text field
+ function getSelection(field){
+ var text = "";
+ if( field.setSelectionRange ){
+ text = field.value.substring(field.selectionStart, field.selectionEnd);
+ } else if( document.selection ){
+ var range = document.selection.createRange();
+ if( range.parentElement() == field ){
+ text = range.text;
+ }
+ }
+ return text;
+ };
+
+ // set the text selected in a text field
+ function setSelection(field, start, end) {
+ if( field.createTextRange ){
+ var selRange = field.createTextRange();
+ selRange.collapse(true);
+ selRange.moveStart("character", start);
+ selRange.moveEnd("character", end);
+ selRange.select();
+ } else if( field.setSelectionRange ){
+ field.setSelectionRange(start, end);
+ } else {
+ if( field.selectionStart ){
+ field.selectionStart = start;
+ field.selectionEnd = end;
+ }
+ }
+ field.focus();
+ };
+
+ function scrollIntoView($el, center){
+ var el = $el[0];
+ var scrollable = $keylist[0];
+ // get the padding which is need to adjust the scrollTop
+ var s = {pTop: parseInt($keylist.css("paddingTop"), 10)||0, pBottom: parseInt($keylist.css("paddingBottom"), 10)||0, bTop: parseInt($keylist.css("borderTopWidth"), 10)||0, bBottom: parseInt($keylist.css("borderBottomWidth"), 10)||0};
+
+ // scrolling down
+ if( (el.offsetTop + el.offsetHeight) > (scrollable.scrollTop + scrollable.clientHeight) ){
+ scrollable.scrollTop = $el.offset().top + (scrollable.scrollTop - $keylist.offset().top) - ((scrollable.clientHeight/((center == true) ? 2 : 1)) - ($el.outerHeight() + s.pBottom));
+ // scrolling up
+ } else if( el.offsetTop - s.bTop - s.bBottom <= (scrollable.scrollTop + s.pTop + s.pBottom) ){
+ scrollable.scrollTop = $el.offset().top + (scrollable.scrollTop - $keylist.offset().top) - s.pTop;
+ }
+ };
+
+ // run the init callback (some keyboard entry methods will manage this callback manually)
+ if( settings.init != null ) settings.init.apply(thismenu, [$input, $hidden, $list]);
+
+ };
+
+})(jQuery);
diff --git a/src/main/webapp/js/jquery.mcdropdown.min.js b/src/main/webapp/js/jquery.mcdropdown.min.js
new file mode 100644
index 0000000..7852092
--- /dev/null
+++ b/src/main/webapp/js/jquery.mcdropdown.min.js
@@ -0,0 +1,22 @@
+(function($){
+/*
+ * mcDropdown jQuery Plug-in
+ *
+ * Copyright 2011 Giva, Inc. (http://www.givainc.com/labs/)
+ *
+ * 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.
+ *
+ * Date: 2011-07-25
+ * Rev: 1.3.1
+ */
+$.fn.mcDropdown=function(list,options){var dd;this.each(function(){dd=$.data(this,"mcDropdown");if(dd){return false}new $.mcDropDownMenu(this,list,options)});return dd||this};$.mcDropdown={version:"1.3.1",setDefaults:function(options){$.extend(defaults,options)}};var defaults={minRows:8,maxRows:25,targetColumnSize:2,openFx:"slideDown",openSpeed:250,closeFx:"slideUp",closeSpeed:250,hoverOverDelay:200,hoverOutDelay:0,showFx:"show",showSpeed:0,hideFx:"hide",hideSpeed:0,dropShadow:true,autoHeight:true,lineHeight:19,screenPadding:10,allowParentSelect:false,delim:":",showACOnEmptyFocus:false,valueAttr:"rel",click:null,select:null,init:null};var isIE6=($.browser.version&&$.browser.version<=6);$.mcDropDownMenu=function(el,list,options){var $self,thismenu=this,$list,$divInput,settings,typedText="",matchesCache,oldCache,$keylist,$keylistiframe,bInput,bDisabled=false;$self=$(el);bInput=$self.is(":input");settings=$.extend({},defaults,options);if(settings.click==null){settings.click=function(e,dropdown,settings){if(this.attr(settings.valueAttr)){dropdown.setValue(this.attr(settings.valueAttr))}else{dropdown.setValue($(this.parents("li")[0]).attr(settings.valueAttr))}}}$(document).bind("click",function(e){var $target=$(e.target);var $ul=$target.parents().filter(function(){return this===$list[0]||(!!$keylist&&$keylist[0]===this)});if($ul.length){var bIsParent=$target.is(".mc_parent");if(bIsParent&&$keylist&&$ul[0]===$keylist[0]){updateValue($target.find("> ul > li:first"),false);e.stopPropagation();return false}else{if(!settings.allowParentSelect&&bIsParent){return false}}if($target.not(".mc_root")){hideBranch.apply($target.parent().parent()[0],[e])}if(settings.click!=null&&settings.click.apply($target,[e,thismenu,settings])==false){return false}}thismenu.closeMenu()});$list=(((typeof list=="object")&&!!list.jquery))?list:$(list);$list.appendTo("body").css({position:"absolute",top:-10000,left:-10000}).find("ul").andSelf().css("display","block").each(function(){var $el=$(this);$el.data("width",$el[0].clientWidth)}).css({top:0,left:0,display:"none"});$list.find("> li").addClass("mc_root");$("li > ul",$list).parent().addClass("mc_parent");$divInput=$('<div class="mcdropdown"><a href="#" tabindex="-1"></a><input type="hidden" name="'+(el.name||el.id)+'" id="'+(el.id||el.name)+'" /></div>').appendTo($('<div style="position: relative;"></div>')).parent();var $input=$self.replaceWith($divInput).attr({id:"",name:""});var $hidden=$divInput.find(":input");$divInput=$divInput.find(".mcdropdown").prepend($input);var $divInputClone=$divInput.clone().css({position:"absolute",top:-9999999,left:-999999,visibility:"visible"}).show().appendTo("body");var di={width:$divInputClone.width()-$("a",$divInputClone).width(),height:$divInputClone.outerHeight()};$divInputClone.remove();$.data($hidden[0],"mcDropdown",thismenu);$divInput.parent().height(di.height);if($.browser.safari){setTimeout(function(){$self.width($divInput.width()-$("a",$divInput).width())},100)}$self.width(di.width).filter(":input").attr("autocomplete","off").bind("keypress",checkKeypress).bind("mousedown",function(e){$(this).triggerHandler("focus");e.stopPropagation();return false}).bind("contextmenu",function(){return false}).bind("focus",onFocus).bind("blur",onBlur);if($.browser.msie||$.browser.safari){$self.bind("keydown",function(e){if(",8,9,37,38,39,40,".indexOf(","+e.keyCode+",")>-1){return checkKeypress(e)}})}$("a",$divInput).bind("click",function(e){if(bDisabled){return false}thismenu.openMenu(e);return false});this.setValue=function(value,skipCallback){$hidden.val(value);var name=displayString(value);if(settings.select!=null&&skipCallback!=true){settings.select.apply(thismenu,[value,name])}return $self[bInput?"val":"text"](name)};if(bInput){this.setValue($self[0].defaultValue,true)}this.getValue=function(value){return[$hidden.val(),$self[bInput?"val":"text"]()]};this.openMenu=function(e){if($list.is(":visible")){return(!!e)?thismenu.closeMenu():false}function open(){columnizeList($list).hide();addBindings($list);anchorTo($divInput.parent(),$list,true);$list.find(".mc_hover").removeClass("mc_hover");$list[settings.openFx](settings.openSpeed,function(){scrollToView($list)});if(isIE6&&!!$.fn.bgIframe){$list.bgIframe()}}if(e){open()}else{setTimeout(open,1)}};this.closeMenu=function(e){$list.find("ul:visible").parent().each(function(){hideBranch.apply(this)});removeBindings($list);$list[settings.closeFx](settings.closeSpeed)};this.focus=function(){$self.focus()};this.disable=function(status){bDisabled=!!status;$divInput[bDisabled?"addClass":"removeClass"]("mcdropdownDisabled");$input.attr("disabled",bDisabled)};function getNodeText($el){var nodeContent;var nContents=$el.contents().filter(function(){return(this.nodeType==1)||(this.nodeType==3&&$.trim(this.nodeValue).length>0)});if(nContents[0]&&nContents[0].nodeType==3){nodeContent=nContents[0].nodeValue}else{if(nContents[0]&&nContents[0].nodeType==1){nodeContent=$(nContents[0]).text()}else{nodeContent=""}}return $.trim(nodeContent)}function getTreePath($li){if($li.length==0){return[]}var name=[getNodeText($li)];$li.parents().each(function(){var $el=$(this);if(this===$list[0]){return false}else{if($el.is("li")){name.push(getNodeText($el))}}});return name.reverse()}function displayValue(value){return getTreePath(getListItem(value))}function displayString(value){return displayValue(value).join(settings.delim)}function parseTree($selector){var s=[],level=(arguments.length>1)?++arguments[1]:1;$("> li",$selector).each(function(){var $self=$(this);var $ul=$("> ul",this);s.push({name:getNodeText($self),element:this,children:($ul.length)?parseTree($ul,level):[]})});return s}function addBindings(el){removeBindings(el);$("> li",el).bind("mouseover",hoverOver).bind("mouseout",hoverOut)}function removeBindings(el){$("> li",el).unbind("mouseover",hoverOver).unbind("mouseout",hoverOut)}function scrollToView($el){var p=position($el,true);var sd=getScreenDimensions();if(p.bottom>sd.y){$("html,body").animate({scrollTop:"+="+((p.bottom-sd.y)+settings.screenPadding)+"px"})}}function hoverOver(e){var self=this;var timer=$.data(self,"timer");if(!isNaN(timer)){clearTimeout(timer)}$(this).addClass("mc_hover");$.data(self,"timer",setTimeout(function(){showBranch.apply(self)},settings.hoverOverDelay))}function hoverOut(e){var self=this;var timer=$.data(self,"timer");if(!isNaN(timer)){clearTimeout(timer)}$(this).removeClass("mc_hover");$.data(self,"timer",setTimeout(function(){var $li=$(self);setTimeout(function(){if($li.parent().find("> li.mc_hover").length==0){$li.parents("li").each(function(){var self=this;clearTimeout($.data(self,"timer"));hideBranch.apply(self);if($(this).siblings().filter(".mc_hover").length>0){return false}})}},settings.hoverOverDelay);hideBranch.apply(self)},settings.hoverOutDelay));if(isIE6){e.stopPropagation()}}function getShadow(depth){var shadows=$self.data("shadows");if(!shadows){shadows={}}if(!shadows[depth]){shadows[depth]=$('<div class="mcdropdown_shadow"></div>').appendTo("body");if(!!$.fn.bgIframe){shadows[depth].bgIframe()}$self.data("shadows",shadows)}return shadows[depth]}function showBranch(){var self=this;var $ul=$("> ul",this);if($ul.is(":visible")||($ul.length==0)){return false}$(this).parent().find("> li ul:visible").not($ul).parent().each(function(){hideBranch.apply(this)});columnizeList($ul);addBindings($ul);var depth=$ul.parents("ul").length;var sd=getScreenDimensions();var li_coords=position($(this));$ul.css({top:li_coords.bottom,left:li_coords.marginLeft}).show();var menuBottom=$ul.outerHeight()+$ul.offset().top;if(menuBottom>sd.y){$ul.css("top",li_coords.bottom-(menuBottom-sd.y)-settings.screenPadding)}var showShadow=function(){if(settings.dropShadow){var $shadow=getShadow(depth);var pos=position($ul);$shadow.css({top:pos.top+pos.marginTop,left:pos.left+pos.marginLeft,width:pos.width,height:pos.height}).insertAfter($ul).show();$.data(self,"shadow",$shadow)}};if(settings.showSpeed<=0){showShadow()}else{$ul.hide()[settings.showFx](settings.showSpeed,showShadow)}}function hideBranch(){var $ul=$("> ul",this);if($ul.is(":hidden")||($ul.length==0)){return false}if(settings.dropShadow&&$.data(this,"shadow")){$.data(this,"shadow").hide()}if(isIE6){$ul.css("visibility","hidden").parent().removeClass("mc_hover")}$ul.stop()[settings.hideFx](settings.hideSpeed)}function position($el,bUseOffset){var bHidden=false;if($el.is(":hidden")){bHidden=!!$el.css("visibility","hidden").show()}var pos=$.extend($el[bUseOffset===true?"offset":"position"](),{width:$el.outerWidth(),height:$el.outerHeight(),marginLeft:parseInt($.curCSS($el[0],"marginLeft",true),10)||0,marginRight:parseInt($.curCSS($el[0],"marginRight",true),10)||0,marginTop:parseInt($.curCSS($el[0],"marginTop",true),10)||0,marginBottom:parseInt($.curCSS($el[0],"marginBottom",true),10)||0});if(pos.marginTop<0){pos.top+=pos.marginTop}if(pos.marginLeft<0){pos.left+=pos.marginLeft}pos.bottom=pos.top+pos.height;pos.right=pos.left+pos.width;if(bHidden){$el.hide().css("visibility","visible")}return pos}function anchorTo($anchor,$target,bUseOffset){var pos=position($anchor,bUseOffset);$target.css({position:"absolute",top:pos.bottom,left:pos.left});return pos.bottom}function getScreenDimensions(){var d={scrollLeft:$(window).scrollLeft(),scrollTop:$(window).scrollTop(),width:$(window).width(),height:$(window).height()};d.x=d.scrollLeft+d.width;d.y=d.scrollTop+d.height;return d}function getPadding(el,name){var torl=name=="height"?"Top":"Left",borr=name=="height"?"Bottom":"Right";return(parseInt("0"+$.curCSS(el,"border"+torl+"Width",true),10)+parseInt("0"+$.curCSS(el,"border"+borr+"Width",true),10)+parseInt("0"+$.curCSS(el,"padding"+torl,true),10)+parseInt("0"+$.curCSS(el,"padding"+borr,true),10)+parseInt("0"+$.curCSS(el,"margin"+torl,true),10)+parseInt("0"+$.curCSS(el,"margin"+borr,true),10))}function getListDimensions($el,cols){if(!$el.data("dimensions")){var ddWidth=$divInput.outerWidth();var width=(($el===$list)&&($el.data("width")*cols<ddWidth))?Math.floor(ddWidth/cols):$el.data("width");$el.data("dimensions",{column:width,item:width-getPadding($el.children().eq(0)[0],"width"),height:$el.height()})}return $el.data("dimensions")}function getHeight($el){if(settings.autoHeight===false){return settings.lineHeight}if(!$el.data("height")){$el.data("height",$el.outerHeight())}return $el.data("height")}function columnizeList($el){var $children=$el.find("> li");var items=$children.length;var calculatedCols=Math.ceil(items/settings.maxRows);var cols=!!arguments[1]?arguments[1]:(items<=settings.minRows)?1:(calculatedCols>settings.targetColumnSize)?calculatedCols:settings.targetColumnSize;var widths=getListDimensions($el,cols);var prevColumn=0;var columnHeight=0;var maxColumnHeight=0;var maxRows=Math.ceil(items/cols);var parentLIWidth=$el.parent("li").width();$el.css({visibility:"hidden",display:"block"});$children.each(function(i){var currentItem=i+1;var nextItemColumn=Math.floor((currentItem/items)*cols);var column=Math.floor((i/items)*cols);var $li=$(this);var marginTop;if(prevColumn!=column){marginTop=(columnHeight+1)*-1;columnHeight=0}else{marginTop=0}columnHeight+=(getHeight($li)||settings.lineHeight);$li.css({marginLeft:(widths.column*column),marginTop:marginTop,width:widths.item})[((nextItemColumn>column)||(currentItem==items))?"addClass":"removeClass"]("mc_endcol")[(marginTop!=0)?"addClass":"removeClass"]("mc_firstrow");if(columnHeight>maxColumnHeight){maxColumnHeight=columnHeight}prevColumn=column});if(($el!==$list)&&(maxColumnHeight+(settings.screenPadding*2)>=getScreenDimensions().height)){return columnizeList($el,cols+1)}$el.css("visibility","visible").height(maxColumnHeight);return $el}function getListItem(value){return $list.find("li["+settings.valueAttr+"='"+value+"']")}function getCurrentListItem(){return getListItem($hidden.val())}function onFocus(e){var $current=getCurrentListItem();var value=$self.val().toLowerCase();var treePath=value.toLowerCase().split(settings.delim);var currentNode=treePath.pop();var lastDelim=value.lastIndexOf(settings.delim)+1;typedText=treePath.join(settings.delim)+(treePath.length>0?settings.delim:"");setTimeout(function(){setSelection($self[0],lastDelim,lastDelim+currentNode.length)},0);if(!$keylist){$keylist=$('<ul class="mcdropdown_autocomplete"></ul>').appendTo("body");if(isIE6&&!!$.fn.bgIframe){$keylistiframe=$("<div></div>").bgIframe().appendTo("body")}}var hideResults=!(settings.showACOnEmptyFocus&&(typedText.length==0));var $siblings=($current.length==0||$current.hasClass("mc_root"))?$list.find("> li"):$current.parent().find("> li");showMatches($siblings,hideResults)}var iBlurTimeout=null;function onBlur(e){if(iBlurTimeout){clearTimeout(iBlurTimeout)}iBlurTimeout=setTimeout(function(){var $current=getCurrentListItem();if(!settings.allowParentSelect&&$current.is(".mc_parent")){var value=$current.find("li:not('.mc_parent'):first").attr(settings.valueAttr);thismenu.setValue(value,true)}if(settings.select!=null){settings.select.apply(thismenu,thismenu.getValue())}hideMatches();iBlurTimeout=null},200)}function showMatches($li,hideResults){var bCached=($li===oldCache),$items=bCached?$keylist.find("> li").removeClass("mc_hover mc_hover_parent mc_firstrow"):$li.clone().removeAttr("style").removeClass("mc_hover mc_hover_parent mc_firstrow mc_endcol").filter(":last").addClass("mc_endcol").end();if(!bCached||$keylist.is(":hidden")){$keylist.empty().append($items).width($divInput.outerWidth()-getPadding($keylist[0],"width")).css("height","auto");anchorTo($divInput.parent(),$keylist,true);$items.hover(function(){$keylist.find("> li").removeClass("mc_hover_parent mc_hover");$(this).addClass("mc_hover")},function(){$(this).removeClass("mc_hover")});$items.find("> ul").css("display","none");$keylist.show().css("visibility",(hideResults===true)?"hidden":"visible");if(isIE6){var maxHeight=parseInt($keylist.css("max-height"),10)||0;if((maxHeight>0)&&(maxHeight<$keylist.outerHeight())){$keylist.height(maxHeight)}if(!!$.fn.bgIframe){anchorTo($divInput.parent(),$keylistiframe.css({height:$keylist.outerHeight(),width:$keylist.width()},true).show())}}if(hideResults!==true){scrollToView($keylist)}}if(hideResults===true){$keylist.css({top:"-10000px",left:"-10000px"});if(isIE6&&!!$.fn.bgIframe){$keylistiframe.css("display","none")}}var $current=$keylist.find("li["+settings.valueAttr+"='"+$hidden.val()+"']");$current.addClass("mc_hover"+($current.is(".mc_parent")?"_parent":""));if($current.length>0&&(hideResults!=true)){scrollIntoView($current)}oldCache=matchesCache=$li}function hideMatches(){if(isIE6&&!!$.fn.bgIframe&&$keylistiframe){$keylistiframe.hide()}if($keylist){$keylist.hide()}}function checkKeypress(e){var key=String.fromCharCode(e.keyCode||e.charCode).toLowerCase();var $current=getCurrentListItem();var $lis=($current.length==0||$current.hasClass("mc_root"))?$list.find("> li"):$current.parent().find("> li");var treePath=typedText.split(settings.delim);var currentNode=treePath.pop();var compare=currentNode+key;var selectedText=getSelection($self[0]).toLowerCase();var value=$self.val().toLowerCase();if(e.keyCode==38){moveMatch(-1);return false}else{if(e.keyCode==40){moveMatch(1);return false}else{if(e.keyCode==27){typedText="";thismenu.setValue("");showMatches($list.find("> li"));return false}else{if(e.keyCode==8||e.keyCode==37){compare=(e.keyCode==37)?"":currentNode.substring(0,currentNode.length-1);if(selectedText==currentNode){currentNode=""}if(treePath.length>0&&currentNode.length==0){updateValue($current.parent().parent());return false}else{if(selectedText==value){typedText="";thismenu.setValue("");return false}}}else{if(e.keyCode==9||e.keyCode==13||e.keyCode==39||key==settings.delim){var $first=$current.find("> ul > li:first");if($first.length>0){updateValue($first)}else{if($.browser.msie){setSelection($self[0],0,0)}if(e.keyCode==9){$self.triggerHandler("blur");hideMatches();return true}else{$self.trigger("blur");hideMatches()}}return false}else{if(selectedText==value){typedText="";compare=key}}}}}}matchesCache=findMatches($lis,compare);if(matchesCache.length>0){typedText=treePath.join(settings.delim)+(treePath.length>0?settings.delim:"")+compare;updateValue(matchesCache.eq(0),true)}else{compare=compare.length?compare.substring(0,compare.length-1):"";matchesCache=findMatches($lis,compare);if(matchesCache.length>0){showMatches(matchesCache)}else{hideMatches()}}e.preventDefault();return false}function moveMatch(step){var $current=getCurrentListItem(),$next,pos=0;if($current.length==0){$current=matchesCache.filter(".mc_hover, .mc_hover_parent")}if($current.length==0||$keylist.is(":hidden")){$current=matchesCache.eq(0);step=0}matchesCache.each(function(i){if(this===$current[0]){pos=i;return false}});if(!matchesCache||matchesCache.length==0||$current.length==0){return false}pos=pos+step;if(pos<0){pos=matchesCache.length-1}else{if(pos>=matchesCache.length){pos=0}}$next=matchesCache.eq(pos);updateValue($next,true)}function findMatches($lis,compare){var matches=$([]);$lis.each(function(){var $li=$(this),label=getNodeText($li);if(label.substring(0,compare.length).toLowerCase()==compare){matches=matches.add($li)}});return matches}function updateValue($li,keepTypedText){var $siblings=keepTypedText?matchesCache:($li.length==0||$li.hasClass("mc_root"))?$list.find("> li"):$li.parent().find("> li");var treePath=getTreePath($li);var currentNode=treePath.pop().toLowerCase();if(!keepTypedText){typedText=treePath.join(settings.delim).toLowerCase()+(treePath.length>0?settings.delim:"")}thismenu.setValue($li.attr(settings.valueAttr),true);setSelection($self[0],typedText.length,currentNode.length+typedText.length);$siblings.filter(".mc_hover,.mc_hover_parent").removeClass("mc_hover mc_hover_parent");$li.addClass("mc_hover"+($li.is(".mc_parent")?"_parent":""));showMatches($siblings)}function getSelection(field){var text="";if(field.setSelectionRange){text=field.value.substring(field.selectionStart,field.selectionEnd)}else{if(document.selection){var range=document.selection.createRange();if(range.parentElement()==field){text=range.text}}}return text}function setSelection(field,start,end){if(field.createTextRange){var selRange=field.createTextRange();selRange.collapse(true);selRange.moveStart("character",start);selRange.moveEnd("character",end);selRange.select()}else{if(field.setSelectionRange){field.setSelectionRange(start,end)}else{if(field.selectionStart){field.selectionStart=start;field.selectionEnd=end}}}field.focus()}function scrollIntoView($el,center){var el=$el[0];var scrollable=$keylist[0];var s={pTop:parseInt($keylist.css("paddingTop"),10)||0,pBottom:parseInt($keylist.css("paddingBottom"),10)||0,bTop:parseInt($keylist.css("borderTopWidth"),10)||0,bBottom:parseInt($keylist.css("borderBottomWidth"),10)||0};if((el.offsetTop+el.offsetHeight)>(scrollable.scrollTop+scrollable.clientHeight)){scrollable.scrollTop=$el.offset().top+(scrollable.scrollTop-$keylist.offset().top)-((scrollable.clientHeight/((center==true)?2:1))-($el.outerHeight()+s.pBottom))}else{if(el.offsetTop-s.bTop-s.bBottom<=(scrollable.scrollTop+s.pTop+s.pBottom)){scrollable.scrollTop=$el.offset().top+(scrollable.scrollTop-$keylist.offset().top)-s.pTop}}}if(settings.init!=null){settings.init.apply(thismenu,[$input,$hidden,$list])}}})(jQuery); \ No newline at end of file
diff --git a/src/main/webapp/wayf-ndn.jsp b/src/main/webapp/wayf-ndn.jsp
index cbb2d85..56095a2 100644
--- a/src/main/webapp/wayf-ndn.jsp
+++ b/src/main/webapp/wayf-ndn.jsp
@@ -142,13 +142,17 @@
<head>
<link rel="stylesheet" type="text/css" href="NORDUnet.css"/>
<link type="text/css" href="css/base/jquery-ui.css" rel="stylesheet" />
+ <link type="text/css" href="css/jquery.mcdropdown.min.css" rel="stylesheet" />
<script type="text/javascript" src="js/jquery-1.6.2.js"></script>
<script type="text/javascript" src="js/jquery-ui.js"></script>
+ <script type="text/javascript" src="js/jquery.bgiframe.js"></script>
+ <script type="text/javascript" src="lib/jquery.mcdropdown.min.js"></script>
<title>Identity Provider Selection</title>
<script type="text/javascript">
$(function() {
$("input:submit, input:reset, input:button, a",".button").button();
- $("#sites").menubar({autoExpand: true, buttons: true});
+ $("#selection").mcDropdown('#sites');
+
});
</script>
</head>
@@ -183,12 +187,13 @@ $(function() {
<li style="vertical-align: top; margin-left: 50px;">
<h1>Select an identity provider</h1>
<p class="text">The service you are trying to use require that you identify yourself. Please select your identity provider below...</p>
-
+ <input type="text" name="selection" id="selection" value="" />
<logic:present name="siteLists" scope="request">
<ul id="sites">
<logic:present name="cookieList" scope="request">
<li>
- <a href="#recently-visited">Recently Visited</a>
+ <!-- a href="#recently-visited">Recently Visited</a -->
+ Recently Visited
<ul>
<logic:iterate id="site" name="cookieList">
<li>
@@ -238,7 +243,8 @@ $(function() {
</logic:present>
<logic:iterate id="siteset" name="siteLists">
<li>
- <a href="#<jsp:getProperty name="siteset" property="name"/>"><jsp:getProperty name="siteset" property="name"/></a>
+ <!-- a href="#<jsp:getProperty name="siteset" property="name"/>"><jsp:getProperty name="siteset" property="name"/></a -->
+ <jsp:getProperty name="siteset" property="name"/>
<ul>
<logic:iterate id="site" name="siteset" property="sites">
<li>