⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 jquery.mcdropdown.js

📁 Ajax学习的一个经典范例
💻 JS
📖 第 1 页 / 共 3 页
字号:
			 */ 
			$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 + -