// REQUIRES domutil.js - BK // Some string constants that will be very useful ... // ID : contiguous DIV ID names // PREF : a prefix to a DIV ID // DIR : a direction of motion // Prefixes and Constants var MINIQ_AREA_MAIN = 0; var MINIQ_AREA_JUSTADDED = 1; var CLASS_MINIQ_ROW = "mqr"; var CLASS_MINIQ_ROW_NONMOVABLE = "mqr_nomove"; var PREF_DRAGGABLE = "dd_"; var PREF_MINIQ = "mq_"; var PREF_MINIQ_INDICATOR = "mqi_"; var PREF_MINIQ_TITLE = "mqt_"; var PREF_MINIQ_NUM = "mqn_"; var PREF_MINIQ_JUSTADDED = "mqja_"; var PREF_MINIQ_JUSTADDED_INDICATOR = "mqjai_"; var PREF_MINIQ_JUSTADDED_TITLE = "mqjat_"; var PREF_MINIQ_JUSTADDED_NUM = "mqjan_"; var ID_JUSTADDED_INDICATOR = "jaInd"; var ID_TOP_BOUNDARY = "mqTop"; var ID_BOTTOM_BOUNDARY = "mqBot"; var DIR_DOWN = 0; var DIR_UP = 1; var TRIPPER_BUFFER_SIZE = 4; var MAX_QUEUE_TO_SHOW = 10; // also defined in miniQueue.jsp // END Prefixes and Constants // Colors var baseColor = "#FFFFFF"; var movedColor = baseColor; // was #ecedff var selectedColor = "#FAF1D5"; var justAddedColor = "#FAE096"; var borderColor = "#3b92ca"; var indicatorColdColor = "#ffffff"; var indicatorHotColor = "#CC0000"; // END Colors // Position Variables var innerOffsetY = 0; var eventOffsetY = 0; var outerOffsetY = 0; // END Position Variables // Numbers to Track var numDisplayedYourQueue = 0; var qItemNumbers = 0; var jaqItemNumbers = 0; var firstDisplayedJustAddedQueueItem = 0; var slideHeight = 0; // Legacy -- don't tease out yet // END Numbers to Track // Flags var hasCrossedMovie = false; var hasCrossedIndicator = false; var justAddedIndicatorCrossed = null; var movingItemDown = null; var dragDirection = null; // END Flags // Movers and Pointers var marypoppins = null; var clickedPosition = -1; var hotIndicatorId = null; var tripperTop = 0; var tripperBottom = 0; var itemHoveredOver = null; // END Movers and Pointers // Global objects - Tracking var startingPoints = new Object(); var endingPoints = new Object(); var currentStartingPoints = new Object(); var currentEndingPoints = new Object(); var indicatorStartingPoints = new Object(); var indicatorEndingPoints = new Object(); // END Global objects - Tracking // // END constant declarations // // // MiniQueue object detection and engagement systems -- can we work with what has been selected? // function getItem(evt) { if (!marypoppins) { marypoppins = (evt.target) ? evt.target : evt.srcElement; } } function isMiniQueueItem(item) { if (typeof item == "string") item = getNode(item); if (item.className == CLASS_MINIQ_ROW || item.id.indexOf(PREF_MINIQ) != -1) return true; else return false; } function isDraggable(item) { if ( item && item.nodeName == "DIV" && (isMiniQueueItem(item) || item.id.indexOf(PREF_DRAGGABLE) != -1 ) ) return true; else return false; } function getMovieIdFromElementId(elementId) { return elementId.substring(elementId.indexOf("_")+1, elementId.length); } function getPositionFromElementId(elementId) { return elementId.substring(elementId.indexOf("_")+1, elementId.length); } // // END MiniQueue object detection and engagement // // // Position Tracking Functions and Tools // function initializePoints(node) { var newnode = getNode(node); startingPoints[node] = currentStartingPoints[node] = newnode.offsetTop; endingPoints[node] = currentEndingPoints[node] = newnode.offsetTop + newnode.offsetHeight; createBorder(node, null); } function initializeIndicatorPoints(node) { var newnode = getNode(node); indicatorStartingPoints[node] = startingPoints[node] = currentStartingPoints[node] = newnode.offsetTop; indicatorEndingPoints[node] = endingPoints[node] = currentEndingPoints[node] = newnode.offsetTop + newnode.offsetHeight; createBorder(node, null); } function updatePoints(node) { var newnode = document.getElementById(node); currentStartingPoints[node] = newnode.offsetTop; currentEndingPoints[node] = newnode.offsetTop + newnode.offsetHeight; } // // END Position Tracking Functions and Tools // // // Queue and Movie Related Functions // // // Queue Item Object // function changeQueueItemPosition(newpos) { this.startPosition = new Number(this.currentPosition); this.currentPosition = newpos; } // set the start position to the same as the current position after visuals reflect virtual queue function synchronizeQueueItemPosition() { this.startPosition = this.currentPosition; } function itemHasMovedDown() { if (this.startPosition < this.currentPosition) { return true; } else if (this.startPosition > this.currentPosition) { return false; } else { return null; } } // // Creating QueueItems // function initializeQueueItem(id, title, pos, released) { var qi = new QueueItem(id, title, pos, false); if (window.location.search.indexOf(qi.id) != -1) { qi.wasAddedThisPage = true; } custq.addItem(qi); } function initializeJustAddedItem(id, title, pos, released) { var qi = new QueueItem(id, title, pos, true); if (window.location.search.indexOf(qi.id) != -1) { qi.wasAddedThisPage = true; } if (this.firstJustAdded = 0) this.firstJustAdded = pos; if (this.initialFirstJustAdded = 0) this.firstJustAdded; this.lastJustAdded = pos; custq.addItem(qi); } // // END Creating Queue Items // function QueueItem(movieId, movieTitle, firstPos, ja) { this.id = movieId; this.title = movieTitle; this.instantiatedPosition = firstPos; // the Queue position of the item when the page was rendered. this.startPosition = firstPos; // the Queue position of the item before any drag-drop actions. Different from the instantiatedPosition since there may be multiple moves per page. this.currentPosition = firstPos; // the Queue position of the item after any drag-drop actions this.justAdded = ja; // boolean this.changePosition = changeQueueItemPosition; this.syncPosition = synchronizeQueueItemPosition; this.hasMovedDown = itemHasMovedDown; this.hasBeenDragged = false; this.wasAddedThisPage = false; return this; } // // END Queue Item Object // // // Queue Object // // // Accessing QueueItems // function getItemFromQueueByPosition(pos) { // This needs to be a lot smarter about getting justAdded versus normal items // Make it so and remove the hacks that compensate for this var item = this.items[pos]; if (typeof item == "undefined") { item = this.jaItems[pos-this.initialFirstJustAdded]; } return item; } function getItemFromQueueById(movieId) { var qi = null; for (var ii = 0; ii < this.mainSize; ii++) { var item = this.getItem(ii); if (item.id == movieId) { qi = item; break; } } if (qi == null) { for (var ii = 0; ii < this.jaSize; ii++) { var item = this.getItem(ii+this.firstJustAdded); if (item.id == movieId) { qi = item; break; } } } return qi; } // // END Accessing QueueItems // // // Moving QueueItems around // function placeItemAtPosition(item, position) { this.items[position] = item; } function placeJAItemAtPosition(item, position) { this.jaItems[position] = item; } function addItemToEnd(item) { if (item.justAdded == null || !item.justAdded) { this.items[this.mainSize] = item; this.mainSize++; qItemNumbers++; } else { this.jaItems[this.jaSize] = item; this.jaSize++; jaqItemNumbers++; this.initialJASize++; } } function newResortQueue(mover, q_arg) { var insertPoint = mover.currentPosition; var removedFromPoint = mover.startPosition; var offset = 0; if (removedFromPoint < insertPoint) { movingItemDown = true; offset = -1; } else { movingItemDown = false; offset = 1; } var backfillStart = removedFromPoint; var backfillFinish = (insertPoint+offset); if (backfillStart >= custq.mainSize) { backfillStart = custq.mainSize-1; } if (movingItemDown) { for (var ii = backfillStart; ii <= backfillFinish; ii++) { var tempItem = q_arg[ii-offset]; this.placeItem(tempItem, ii); } } else { for (var ii = backfillStart; ii >= backfillFinish; ii--) { var tempItem = q_arg[ii-offset]; this.placeItem(tempItem, ii); } } this.placeItem(mover, insertPoint); } // // END Moving QueueItems around // function Queue() { this.items = new Object(); this.jaItems = new Object(); this.tempItems = new Object(); this.tempJAItems = new Object(); this.mainSize = 0; this.jaSize = 0; this.tempMainSize = 0; this.tempJASize = 0; this.initialJASize = 0; this.numMainAwaitingReleaseTitles = 0; this.numJustAddedAwaitingReleaseTitles = 0; this.addItem = addItemToEnd; this.placeItem = placeItemAtPosition; this.placeJAItem = placeJAItemAtPosition; this.getItem = getItemFromQueueByPosition; this.getItemById = getItemFromQueueById; this.resort = newResortQueue; this.firstJustAdded = 0; this.initialFirstJustAdded = 0; this.lastJustAdded = 0; return this; } // // END Queue Object // // // END Queue and Movie-Related Functions // // // Updating the Page And Interface Functions ... // // Visually slide a MiniQueue node and update its points. Currently unused, but preserve it. function slideMiniQueueNode(slider, amount) { moveNode(slider, amount); updatePoints(slider.id); } // Drop left and right one-pixel borders on a node. Falls back on "borderColor" if none specified. function createBorder(node, color) { if (color == null) color = borderColor; if (typeof node == "string") node = getNode(node); // Sanity check if (node == null || color == null) return; node.style.borderLeft="1px solid " + color; node.style.borderRight="1px solid " + color; } // Highlight the "drop zone" indicators function highlightIndicator(newIndicatorId) { if (hotIndicatorId != null) { document.getElementById(hotIndicatorId).style.background = indicatorColdColor; } if (newIndicatorId != null) { var indicator = document.getElementById(newIndicatorId); indicator.style.background = indicatorHotColor; } hotIndicatorId = newIndicatorId; } // This method isn't attached to an object. It's a quick way to fire off all the tasks that transpire when an item has been moved. function moveQueueItem(item, newpos) { // prepare the request for the move and fire it off item.changePosition(newpos); item.hasBeenDragged = true; custq.resort(item, custq.items); // fire off the request sendChangeRequest(item); // update the queue display updateQueueDisplay(item); } // This function is fragile. Tinker with it at your own peril. "Optimizations" will cause you pain. - BK function updateQueueDisplay(item) { var presyncStartPos = item.startPosition; for (var ii = 0; ii < custq.mainSize; ii++) { var row = getNode(PREF_MINIQ + ii); var titleNode = getNode(PREF_MINIQ_TITLE + ii); var qi = custq.items[ii]; replaceInnerText(titleNode, qi.title); qi.changePosition(ii); qi.syncPosition(); row.style.background = qi.hasBeenDragged ? movedColor : baseColor; updatePoints(PREF_MINIQ + ii); updatePoints(PREF_MINIQ_INDICATOR + ii); } if (item.justAdded || marypoppins.id.indexOf(PREF_MINIQ_JUSTADDED) != -1) { // Because getItemFromQueueByPosition() isn't very smart, we may have grabbed this item from the main Queue array instead of the justAdded array. // Compensate for now by checking to see if the item first clicked was from the JA section. // Both this method and getItemFromQueueByPosition() will need to be changed later. - BK var offset = 1; var backfillStart = presyncStartPos; var backfillFinish = custq.firstJustAdded+offset; var undisplayedJASlots = custq.initialJASize - custq.jaSize; for (var ii = backfillStart; ii >= backfillFinish; ii--) { var visualPositionTarget = ii; var actualPositionTarget = visualPositionTarget - custq.initialFirstJustAdded; var jqi = custq.jaItems[actualPositionTarget-offset]; jqi.changePosition(visualPositionTarget); jqi.syncPosition(); custq.placeJAItem(jqi, actualPositionTarget); var jarow = getNode(PREF_MINIQ_JUSTADDED + visualPositionTarget); var jaTitleNode = getNode(PREF_MINIQ_JUSTADDED_TITLE + visualPositionTarget); var jaNumberNode = getNode(PREF_MINIQ_JUSTADDED_NUM + visualPositionTarget); // Visual shift replaceInnerText(jaTitleNode, jqi.title); replaceInnerText(jaNumberNode, ((jqi.currentPosition+1) + ".")); jarow.style.background = jqi.wasAddedThisPage ? justAddedColor : baseColor; } var blankItem = QueueItem(0, "", 9999, true); custq.placeJAItem(blankItem, undisplayedJASlots); // remove the first slot killNode(PREF_MINIQ_JUSTADDED + (custq.firstJustAdded)); killNode(PREF_MINIQ_JUSTADDED_INDICATOR + (custq.firstJustAdded)); // clean up the list quantities and start points custq.firstJustAdded++; custq.jaSize--; // update the positions of the rest of the JA items for (var ii = custq.firstJustAdded; ii <= custq.lastJustAdded; ii++) { updatePoints(PREF_MINIQ_JUSTADDED + ii); updatePoints(PREF_MINIQ_JUSTADDED_INDICATOR + ii); } // Clear the just added flag. item.justAdded = false; if (custq.jaSize == 0 && custq.numJustAddedAwaitingReleaseTitles == 0) { killNode(ID_JUSTADDED_INDICATOR); } } // resync just in case item.syncPosition(); } // create URL and send off request. This is all in MiniQueueHandler.java function sendChangeRequest(item) { var url = "/MiniQueue?action=1&movieid=" + item.id + "&priority=" + (item.currentPosition+1) + "&mvregion=" + (item.justAdded ? 1 : 2) + "&prevpage=" + escape(window.location.pathname + window.location.search) + "&ncok=y"; window.location.href = url; } // // END Updating the Page ... // // // Rendering Procedures // function getIndicatorDivId(type, indicatorPosition) { return (type == MINIQ_AREA_MAIN ? PREF_MINIQ_INDICATOR : PREF_MINIQ_JUSTADDED_INDICATOR) + indicatorPosition; } function emitIndicator(type, indicatorPosition) { document.write("
");
document.write(" ");
document.write(Number(position)+1);
document.write(". | \n");
document.write("");
document.write(title);
document.write(" | \n");
document.write("
-- | "); document.write(title); document.write(" |