用JavaScript和CSS创建下拉列表

This page is a translated version of the page Create a Drop-Down list using JavaScript and CSS and the translation is 100% complete.

关于如何为维基制作简单的下拉导航列表(不使用javascript和css硬编码的皮肤)的分步说明。


必要条件

能够修改您的MediaWiki:Common.js和MediaWiki:Monobook.css

Common.js代码

/* Any JavaScript here will be loaded for all users on every page load. */

function ddm() {

    // Variables, change these in case you need to set other class names (mmhide_ for 
    // contribute users for example)
    var parentClass = 'isParent'; //gets applied when the LI has a nested UL
    var activeParentClass = 'isActive'; //gets applied when the nested UL is visible
    var preventHoverClass = 'nohover'; //denotes a navigation that should not get any hover effects
    var indicateJSClass = 'dhtml'; //gets applied to the main navigation when JavaScript is available
    var toHideClass = 'hiddenChild'; //gets applied to hide the nested UL
    var toShowClass = 'shownChild'; //gets applied to show the nested UL
    var currentClass = 'current'; //denotes the current active sub element and prevents collapsing
    var d = document.getElementById('nav'); //denotes the navigation element 

    // if DOM is not available stop right here.
    if (!document.getElementById && !document.createTextNode) {
        return;
    }

    // if the navigation element is available, apply the class denoting DHTML capabilities
    if (d) {
        d.className += d.className == '' ? indicateJSClass : ' ' + indicateJSClass;
        var lis, i, firstUL, j, apply;

        // loop through all LIs and check which ones have a nested UL
        lis = d.getElementsByTagName('li');
        for (i = 0; i < lis.length; i++) {
            firstUL = lis[i].getElementsByTagName('ul')[0];
                // if there is a nested UL, deactivate the first nested link and apply the class to show 
                // there is a nested list
            if (firstUL) {
                lis[i].childNodes[0].onclick = function() {
                    return false;
                };
                lis[i].className += lis[i].className == '' ? parentClass : ' ' + parentClass;
                // check if there is a "current" element 
                apply = true;
                if (new RegExp('\\b' + currentClass + '\\b').test(lis[i].className)) {
                    apply = false;
                }
                if (apply) {
                    for (j = 0; j < firstUL.getElementsByTagName('li').length; j++) {
                        if (new RegExp('\\b' + currentClass + '\\b').test(firstUL.getElementsByTagName('li')[j].className)) {
                            apply = false;
                            break;
                        }
                    }
                }
                // if there is no current element, apply the class to hide the nested list
                if (apply) {
                    firstUL.className += firstUL.className == '' ? toHideClass : ' ' + toHideClass;
                    // check if there is a class to prevent hover effects and only apply the function
                    // onclick if that is the case, otherwise apply it onclick and onhover
                    if (new RegExp('\\b' + preventHoverClass + '\\b').test(d.className)) {
                        lis[i].onclick = function() {
                            doddm(this);
                        };
                    } else {
                        lis[i].onclick = function() {
                            doddm(this);
                        };
                        lis[i].onmouseover = function() {
                            doddm(this);
                        };
                        lis[i].onmouseout = function() {
                            doddm(null);
                        };
                    }
                    // if there is a current element, define the list as being kept open and apply the 
                    // classes to show the nested list and define the parent LI as an active one
                } else {
                    lis[i].keepopen = 1;
                    firstUL.className += firstUL.className == '' ? toShowClass : ' ' + toShowClass;
                    lis[i].className = lis[i].className.replace(parentClass, activeParentClass);
                }
            }
        }
    }
    // function to show and hide the nested lists and add the classes to the parent LIs
    function doddm(o) {
        var childUL, isobj, swap;

        // loop through all LIs of the navigation       
        lis = d.getElementsByTagName('li');
        for (i = 0; i < lis.length; i++) {
            isobj = lis[i] == o;
            // function to exchange class names in an object
            swap = function(tmpobj, tmporg, tmprep) {
                tmpobj.className = tmpobj.className.replace(tmporg, tmprep);
            };
            // if the current LI does not have an indicator to be kept visible
            if (!lis[i].keepopen) {
                childUL = lis[i].getElementsByTagName('ul')[0];
                // check if there is a nested UL and if the current LI is not the one clicked on
                // and exchange the classes accordingly (ie. hide all other nested lists and 
                // make the LIs parent rather than active.
                if (childUL) {
                    if (new RegExp('\\b' + preventHoverClass + '\\b').test(d.className)) {
                        if (new RegExp('\\b' + activeParentClass + '\\b').test(lis[i].className)) {
                            swap(childUL, isobj ? toShowClass : toHideClass, isobj ? toHideClass : toShowClass);
                            swap(lis[i], isobj ? activeParentClass : parentClass, isobj ? parentClass : activeParentClass);
                        } else {

                            swap(childUL, isobj ? toHideClass : toShowClass, isobj ? toShowClass : toHideClass);
                            swap(lis[i], isobj ? parentClass : activeParentClass, isobj ? activeParentClass : parentClass);
                        }
                    } else {
                        swap(childUL, isobj ? toHideClass : toShowClass, isobj ? toShowClass : toHideClass);
                        swap(lis[i], isobj ? parentClass : activeParentClass, isobj ? activeParentClass : parentClass);
                    }
                }
            }
        }
    }
}
window.onload = function() {
    ddm();
    // add other functions to be called onload below
};

Monobook.css

/*Main Line Not Just Link Margin - From left Side*/
ul#nav {
  margin: 3px;
  padding: 2px;
  list-style-type: none;
  border: none;
  background: #fff;
  width: auto;
}

/*Drop Menu Line Colors that "flash" to load Menu*/
ul#nav li ul {
  background: #fff;
  margin: 0px;
  padding: 5px;
  width: auto;
}

ul#nav li {
  position: relative;
  margin: 5px;
  width: auto;
  padding: 5px;
  list-style-type: none;
  background: #333;
  color: #333;
  line-height: 150%;
}

/*Main Link Font Color and "loading border" set to fff for invisibility*/
ul#nav a {
  border: 1px solid #fff;
  color: #333;
  text-decoration: none;
  display: block;
}

/*Mouse over option text color*/
ul#nav a:hover {
  border: 1px inset #333;
  background: #333;
  color: #333;
}

/*Color of Text option drop down without mouse on them.*/
ul#nav li li a {
  padding-left: 1em;
  color: #006AFF;
  text-decoration: none;
  display: block;
}

ul#nav li li a:hover {
  background: #cef;
}

/* DDM relative dropdown example */
.hiddenChild {
  position: absolute;
  left: -999em;
}

.shownChild {
  left: -1px;
}

p {
  clear: both;
  float: none;
}

/*Parent initial border information white fff set to hide "optional options area"*/
ul#nav.dhtml {
  list-style-image: none;
  display: block;
  position: relative;
  width: auto;
  border: 2px solid #fff;
  background: #333;
  margin: 2px;
  padding: 2px;
  list-style-type: none;
  height: 1.5em;
}

/*WIDTH IS TOP OPTION WIDTH. (OPTION WIDTH - 1)*/
ul#nav.dhtml li {
  position: relative;
  float: left;
  width: 9em;
  border-right: 1px solid #333;
  border-top: 1px solid #333;
  border-left: 1px solid #333;
  border-bottom: 1px solid #333;
}

/*Initial background color of options with mouse hovered over main link*/
ul#nav.dhtml ul {
  list-style-image: none;
  display: block;
  top: 1.5em;
  position: absolute;
  border-top: 1px solid #333;
  border-right: 1px solid #333;
  border-left: 1px solid #333;
  background: #333;
  width: auto;
  z-index: 10;
}

ul#nav.dhtml li a,
ul#nav.dhtml li a:hover {
  border: none;
  background: #333;
}

ul#nav.dhtml li a {
  padding: 0 .5em;
  background: #333;
}

/*Options background color when main category is highlighted with mouse and options not selected WIDTH IS OPTIONS WIDTH*/
ul#nav.dhtml ul li {
  border: none;
  width: 9em;
  background: #fff;
}

/*No Mouse On Main Link Background*/
ul#nav.dhtml li.isParent {
  background: #cef;
}

/*Yes Mouse On Main Link Background*/
ul#nav.dhtml li.isActive {
  background: #fff;
}

ul#nav.dhtml li.isActive a {
  background: #cef;
}

ul#nav.dhtml li.isActive ul a {
  padding: 0 .5em;
}

ul#nav.dhtml a:hover {
  background: #333;
}

ul#nav.dhtml li.isParent a:hover {
  background: #333;
}

ul#nav.dhtml li.isActive ul a:hover {
  background: #333;
}


Wiki示例中使用的代码/菜单/列表

<ul id="nav">
  <li><span class="plainlinks">'''[[PageLinkLocated|NameofLink]]'''</span>
    <ul>
      <li><span class="plainlinks">'''[[Option1]]'''</span></li>
      <li><span class="plainlinks">'''[[Option2]]'''</span></li>
      <li><span class="plainlinks">'''[[Option3]]'''</span></li>
      <li><span class="plainlinks">'''[[Option4]]'''</span></li>
      <li><span class="plainlinks">'''[[Option5]]'''</span></li>
    </ul>
  </li>
</ul>

从而在指定位置创建一个功能齐全的下拉列表。

示例代码:

<ul id="nav">
  <li><span class="plainlinks">'''[[Main_Page|Shortcuts]]'''</span>
    <ul>
      <li><span class="plainlinks">'''[[Carnivores]]'''</span></li>
      <li><span class="plainlinks">'''[[Herbivores]]'''</span></li>
      <li><span class="plainlinks">'''[[Reptiles]]'''</span></li>
      <li><span class="plainlinks">'''[[Amphibians]]'''</span></li>
      <li><span class="plainlinks">'''[[Mammals]]'''</span></li>
    </ul>
  </li>
</ul>


参考资料

YADM http://www.onlinetools.org/tools/yadm/
维基媒体论坛支持 http://www.mwusers.com/forums
CSS代码学校支持 http://www.w3schools.com/Css/default.asp

参见