📄 jquery.mcdropdown.js
字号:
*/
$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");
}
// 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);
};
function onBlur(e){
// 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();
};
function showMatches($li){
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);
// show the list
$keylist.show();
// 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.height()) ) $keylist.height(maxHeight);
// anchor the iframe behind the scrollable list
if( !!$.fn.bgIframe ) anchorTo($divInput.parent(), $keylistiframe.css({height: $keylist.height(), width: $keylist.width()}).show())
}
// scroll the list into view
scrollToView($keylist);
}
// 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 ) scrollIntoView($current);
// update the cache
oldCache = matchesCache = $li;
};
function hideMatches(){
// hide the bgiframe
if( isIE6 && !!$.fn.bgIframe ) $keylistiframe.hide();
$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 ) ($self[0], 0, 0);
// blur out of the field
$self.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 ){
// 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, keepTypedText);
};
// 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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -