1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183
| function RecordingsList(id) {
if (arguments.length > 0)
this.init(id);
}
RecordingsList.prototype.init = function(id) {
this.id = id;
this.idElt = document.getElementById(id);
if (this.idElt == undefined) return;
this.idStyle = document.defaultView.getComputedStyle(this.idElt, null);
this.listElt = this.idElt.getElementsByTagName("ul")[0];
this.listItemElt = this.listElt.getElementsByTagName("li");
this.listLength = this.listItemElt.length;
this.listItemStyle = document.defaultView.getComputedStyle(this.listItemElt[0], null);
this.listItemHeight = parseInt(this.listItemStyle.height)
+ parseInt(this.listItemStyle.paddingTop)
+ parseInt(this.listItemStyle.paddingBottom)
+ parseInt(this.listItemStyle.borderTopWidth)
+ parseInt(this.listItemStyle.borderBottomWidth)
+ parseInt(this.listItemStyle.marginTop)
+ parseInt(this.listItemStyle.marginBottom);
this.addHighlight();
this.addFaders();
this.addVideoPreviews();
this.addFocusHandlers();
// Nav left and nav right should do nothing for any list item.
for (var li = 0; li < this.listLength; li++) {
this.listItemElt[li].style.navLeft = "#" + this.listItemElt[li].id;
this.listItemElt[li].style.navRight = "#" + this.listItemElt[li].id;
}
// Down from bottom goes to top, and vice versa
this.listItemElt[0].style.navUp = "#" + this.listItemElt[this.listLength - 1].id;
this.listItemElt[this.listLength - 1].style.navDown = "#" + this.listItemElt[0].id;
this.scroller = new VerticalScroller(this.listElt);
// Make sure the first list item is under the highlight and has focus.
this.listItemElt[0].focus();
}
// The highlight is styled and positioned by CSS.
// We just add the appropriate element to the document.
// NB it's added to the document, NOT into the div.
// This is to ensure it isn't affected by any styles set for
// the div itself.
RecordingsList.prototype.addHighlight = function() {
var highlight = document.createElement("div");
highlight.className = "highlight";
document.body.appendChild(highlight);
// We'll need to know where it's actually positioned, relative
// to the top of the list, so that we can move list items into
// the appropriate position.
this.highlightDelta =
parseInt(document.defaultView.getComputedStyle(highlight, null).top)
- parseInt(this.idStyle.top);
}
// Same applies to the two faders.
RecordingsList.prototype.addFaders = function() {
var topFader = document.createElement("div");
var botFader = document.createElement("div");
topFader.className = "fade top";
botFader.className = "fade bottom";
document.body.appendChild(topFader);
document.body.appendChild(botFader);
}
// Create an array of Image objects, holding video previews.
// Add an img element to the document with the appropriate id.
// These are then tied together in the showVideo method.
// A more exotic example might create an img element for each image
// and animate between the images.
RecordingsList.prototype.addVideoPreviews = function() {
this.vidPreview = new Array();
for (var li = 0; li < this.listLength; li++) {
var id = this.listItemElt[li].id;
var imgPath = "images/show-" + id + ".jpg";
this.vidPreview[id] = document.createElement("img");
this.vidPreview[id].id = "vidPreview-"+id;
this.vidPreview[id].src = imgPath;
this.vidPreview[id].className = "vidPreview";
document.body.appendChild(this.vidPreview[id]);
}
}
// When a list item receives focus, it is moved into the highlight area.
RecordingsList.prototype.addFocusHandlers = function() {
var me = this;
for (var li = 0; li < this.listLength; li++) {
this.listItemElt[li].itemDelta = li * this.listItemHeight; // handy
this.listItemElt[li].addEventListener("focus",
function(e) { me.highlightElt(e.target) }, false);
// Show and hide the video preview appropriately.
this.listItemElt[li].addEventListener("focus",
function(e) { me.showVideo(e.target) }, false);
this.listItemElt[li].addEventListener("blur",
function(e) { me.hideVideo(e.target) }, false);
}
}
// Move the list so that elt sits inside the highlight area.
RecordingsList.prototype.highlightElt = function(elt) {
this.scroller.scrollTo(this.highlightDelta - elt.itemDelta);
}
// Show the video preview for this recording.
RecordingsList.prototype.showVideo = function(elt) {
this.vidPreview[elt.id].style.play = "focus"
;
}
// Hide the video preview for this recording.
RecordingsList.prototype.hideVideo = function(elt) {
this.vidPreview[elt.id].style.display = "none";
}
// A VerticalScroller object scrolls an element up or down smoothly.
// Instantiate it with an element, and call the scrollTo method
// to scroll that element to a new position.
function VerticalScroller(elt) {
if (arguments.length > 0)
this.init(elt);
}
VerticalScroller.prototype.init = function(elt) {
this.elt = elt;
// How far the list is moved up or down from its top=0 position.
// Initially, the style sheet determines this. We store locally
// to avoid calling getComputedStyle repeatedly.
this.currentDelta = parseInt(document.defaultView.getComputedStyle(this.elt, null).top);
// Holds a timeout handle so we can cancel scrolling when we need to.
this.scrollHandle = null;
}
VerticalScroller.prototype.scrollTo = function(targetDelta) {
if (this.scrollHandle) clearTimeout(this.scrollHandle);
var diff = targetDelta - this.currentDelta;
this.scrollAnim(diff, 8); // magic move factor
}
// To get a move-past-target-and-spring-back effect we note that
// 8+7+6+5+4+3+2+1+0-1-2-3 = 30
// So decrementing a moveFactor from 8 to -3, and moving
// moveFactor/30 of the total distance each time, eventually gets
// us there. We could just scroll a fixed amount each time, of course,
// but this looks prettier.
VerticalScroller.prototype.scrollAnim = function(diff, moveFactor) {
var me = this;
this.currentDelta += (moveFactor * diff) / 30;
this.elt.style.top = this.currentDelta + "px";
if (moveFactor != -3)
this.scrollHandle = setTimeout(function() { me.scrollAnim(diff, moveFactor - 1) }, 35);
}
// Initialise the page
function initPage() {
var stateList = new RecordingsList("rec-list");
if (top.loadListener) top.loadListener.hasLoaded();
}
window.onload = initPage; |
Partager