// Paging list // Written so that it can be easily subclassed, with easy access to // the parent constructor from the subclass. function PagingList(id, topItem, visibleItems) { if (arguments.length > 0) this.init(id, topItem, visibleItems); } PagingList.prototype.init = function(id, topItem, visibleItems) { this.id = id; this.idElt = document.getElementById(id); if (this.idElt == undefined) return; if (topItem != undefined) this.topItem = topItem; if (visibleItems != undefined) this.visibleItems = visibleItems; // We'll be showing/hiding this.listItemElt elements // By contract we can assume the list is the first UL element, // containing one LI element per list item. this.listElt = this.idElt.getElementsByTagName("ul")[0]; this.listItemElt = this.listElt.getElementsByTagName("li"); this.listLength = this.listItemElt.length; this.addPagers(); // Contract between presentation and behaviour states that the // list items are initially hidden. The list itself, however, is // displayed. This method displays each list item individually. this.showList(); } // Inherited unless overridden. PagingList.prototype.visibleItems = 9; PagingList.prototype.topItem = 0; // Add a pager to the list. // A pager's purpose is to page a list in a particular direction // by calling a list's function on receiving a focus event. // It adds a div element to the document with the appropriate ID // and class. // It's up to presentation to display this element appropriately. PagingList.prototype.addPagers = function() { var me = this; this.upPager = this.createPagerElt(function() { me.pageUp() }, this.id + "-pagerUp", "pager up"); this.downPager = this.createPagerElt(function() { me.pageDown() }, this.id + "-pagerDown", "pager down"); // Add to document before and after the list this.idElt.insertBefore(this.upPager, this.listElt); this.idElt.insertBefore(this.downPager, this.listElt.nextSibling); } PagingList.prototype.createPagerElt = function(fn, id, className) { var pagerElt = document.createElement("div"); // Assume id is unique. pagerElt.id = id; pagerElt.className = className; pagerElt.addEventListener("focus", fn, false); return pagerElt; } PagingList.prototype.pageUp = function() { // No paging: just refocus first item. if (this.topItem == 0) { this.moveFocusToItem(0); return; } // Never go above the first list item var newTop = Math.max(this.topItem - this.visibleItems, 0); // Focus goes to the item above the last CURRENTLY visible item // however much is paged. var newFocus = this.topItem - 1; this.pageTo(newTop, newFocus); } PagingList.prototype.pageDown = function() { // No paging: just refocus last item. if (this.topItem == this.listLength - this.visibleItems) { this.moveFocusToItem(this.listLength - 1); return; } // Mustn't show items past the end of the list. var newTop = Math.min(this.topItem + this.visibleItems, this.listLength - this.visibleItems); // Focus goes on the one below the last CURRENTLY visible item // however much is paged. var newFocus = this.topItem + this.visibleItems; this.pageTo(newTop, newFocus); } PagingList.prototype.pageTo = function(top, focus) { this.hideList(); this.topItem = top; this.showList(); this.moveFocusToItem(focus); } PagingList.prototype.moveFocusToItem = function(pos) { this.listItemElt[pos].focus(); } PagingList.prototype.showList = function() { for (var li = this.topItem; li < this.topItem + this.visibleItems; li++) { this.listItemElt[li].style.display = "block"; } } PagingList.prototype.hideList = function() { for (var li = this.topItem; li < this.topItem + this.visibleItems; li++) { this.listItemElt[li].style.display = "none"; } } // Initialise the page. function initPage() { var stateList = new PagingList("state-list"); //var stateList = new ScrollingList("state-list"); stateList.moveFocusToItem(0); } window.onload = initPage;
css:
/* Style sheet for paging-list.html */ body { margin: 0; background-color: #fc6; } #state-list { position: absolute; top: 100px; left: 20%; } .list { margin: 0; } .list h1 { display: none; } .list ul { margin: 0; padding: 0; } .list li { display: none; /* changed to display: block; by behaviour code */ background-color: #da4; border: 2px solid #b82; margin: 0.25em 0; padding: 0 0.5em; font: bold 16pt sans-serif; width: 10em; -ant-user-input: enabled; } .list li:focus { border: 2px solid #369; background-color: #69c; -ant-highlight-color: transparent; } /* These are created by the behavioural code. */ .pager { -ant-user-input: enabled; height: 1px; background-color: transparent; } .pager:focus { -ant-highlight-color: transparent; } /* Nothing extra */ .pager.up { } .pager.down { }
前段时间看老外一个翻页的代码,今天改到这儿,又看了一遍,发现这段代码中有两点需要做下笔记:
一:
this.idElt.insertBefore(this.downPager, this.listElt.nextSibling);
这里的nextSibling是js内置的对象,我的理解是紧挨着listELt的元素,但listElt只有一个元素,没有和它并列的元素,所以这里不太明白。
insertBefore类似于appendChild的功能,就是在父元素的子元素前面插入一个元素
parentElement.insertBefore( newElement, referenceElement);
又google一下,发现这里有很多人会遇到问题,大概是firefox(IE不会,没有试验过)会把空格或者换行符当做一个dom对象来处理,所以在使用nextSlibling的时候得不到元素:
所以都会通过判断元素类型来处理:
/* Credit to John Resig for this function taken from Pro JavaScript techniques */ function next(elem) { do { elem = elem.nextSibling; } while (elem && elem.nodeType != 1); return elem; } var elem = document.getElementById('the_id'); var nextElem = next(elem);
或者:
Object.prototype.nextObject = function() { var n = this; do n = n.nextSibling; while (n && n.nodeType != 1); return n; }
二:
在js中给一个元素加入css的类,用空格代替样式表中的".":
this.upPager = this.createPagerElt(function() { me.pageUp() }, this.id + "-pagerUp", "pager up");
这里的pager up 在css中是pager类下面的up类 .pager .up{} (不知道如果想要加以id为标示的css类该怎么加)
参考:
http://stackoverflow.com/questions/868407/hide-an-elements-next-sibling-with-javascript
http://roseindia.net/javascript/javascript-insertbefore-method.shtml