Zoomii Interface Enhancer

By Pedro Ruano Last update Jun 27, 2008 — Installed 26 times.
// ==UserScript==
// @name          Zoomii Interface Enhancer
// @namespace	  http://pwp.netcabo.pt/pruano/greasemonkey/zoomii_enhancer
// @description	  Enhances the cool zoomii interface to Amazon by adding a few features, like keyboard shortcuts.
// @include       http*://zoomii.com/*
// ==/UserScript==

// This is a Greasemonkey user script

// Shortcuts:
//
// Up arrow - move up
//  Down arrow - move down
//  Left arrow - move left
//  Right arrow - move right
// c - show/hide category list
// h - show/hide left command bar
// +  - zoom in
// -  - zoom out
// f - search

// --------------------------------------------------------------------
// Changelog
//
// 0.1
//  First Release.
// --------------------------------------------------------------------

(function() {

// Constants
doDebug = false;

// globals
var components = { hoverBox: null, searchBox: null, categories: null, commands: null };
 
const HANDLERS_TABLE = {
    // Up-Arrow  :move up
	38: moveUp,

    // Down-Arrow :move down
	40: moveDown,

    // Left-Arrow :move left
	37: moveLeft,

    // Right-Arrow :move right
	39 :moveRight,
	
    // + :zoom in
	107: zoomIn,

    // - :zoom out
	109: zoomOut,
	
	// 'h' - Shows/hides command box
	72: toggleHoverBoxDisplay,
	
	// 'c' - Opens category list
	67: toggleCategoryListDisplay,
	
    // 'f' - Search
    70: searchCommand,

};

if (isLoaded()) { 
  window.addEventListener('keydown', keyHandler, false);
  myLog("Loading");
}

// Logs given string to the JavaScript Console if in debug mode
function myLog(toLog) {
   if(doDebug){
     GM_log(toLog);
  }
}

// ---XPath helper----
//Run a particular XPath expression _p_ against the context node _context_ (or the document, if not provided).
//Returns the results as an array.
//Note: Use relative xpath if context provided
//Found in GreaseSpot: http://wiki.greasespot.net/Code_snippets#XPath_helper

function $x(p, context) {
  if (!context) context = document;
  var i, arr = [], xpr = document.evaluate(p, context, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
  for (i = 0; item = xpr.snapshotItem(i); i++) arr.push(item);
  return arr;
}


function getNode(nodeId) {
	return document.getElementById(nodeId);
}

function isLoaded() {
  return getNode("contents");
}

function runCommands(commands) {
  for (var i=0; i < commands.length; i++) {
    var command = commands[i];
 
    // A one second pause between commands seems to be enough for LAN/broadband
    // connections
    setTimeout(commands[i], 100 + 1000 * i);
  }
}

function keyHandler(event) {
  // Apparently we still see Firefox shortcuts like control-T for a new tab - 
  // checking for modifiers lets us ignore those
  if (event.altKey || event.ctrlKey || event.metaKey || event.keyCode == 16) {
    return false;
  }
  
  if(getNode("video_div")){
	return false;
  }
  
  if(isBookDetailOpen()){
	return false;
  }
  
  // We also don't want to interfere with regular user typing
  if (event.target && event.target.nodeName) {
    var targetNodeName = event.target.nodeName.toLowerCase();
    if (targetNodeName == "textarea" ||
        (targetNodeName == "input" && event.target.type &&
         event.target.type.toLowerCase() == "text")) {
      return false;
    }
  }
 
  //alert("Event: " + event.keyCode);
  
  if (event.keyCode in HANDLERS_TABLE) {
    runCommands([HANDLERS_TABLE[event.keyCode]]);
    return true;
  }
  
  return false;
}

function getSearchBox(){
	if(components.searchBox != null){
		return components.search;
	}
	myLog("Setting searchBox");
	var hoverBox = getHoverBox();
	if(hoverBox == null){
		return null;
	}
	var searchBoxXPath = "//input[@type='text']";
	var result = $x(searchBoxXPath,hoverBox);
	if(result.length != 1){
		myLog("Failed to find the search box");
		return null;
	}
	components.searchBox = result[0]
	
	return components.searchBox;
}

function getBookDetail(){
	var bookDetailXPath = "//div[@id=\"contents\"]/div/div[2]/div[7]";
	var result = $x(bookDetailXPath);
	if(result.length == 0){
		myLog("Failed to find the book detail div");
		return null;
	}
	return result[0];
}

function isBookDetailOpen(){
	var bookDetail = getBookDetail();
	
	if(bookDetail == null || bookDetail.style.display != "block"){
		return false;
	}
	
	return true;
}

function getHoverBox(){
	if(components.hoverBox != null){
		return components.hoverBox;
	}
	myLog("Setting hoverBox");
	var hoverBoxXPath = "//div[@id=\"contents\"]/div/div[2]/div[6]";
	var result = $x(hoverBoxXPath);
	if(result.length == 0){
		myLog("Failed to find the hover box div");
		return null;
	}
	components.hoverBox = result[0]
	
	return components.hoverBox;
}

function hideHoverBox(){
	var hoverBox = getHoverBox();
	if(hoverBox){
		myLog("Hiding");
		hoverBox.style.visibility = "hidden";
	}
}

function showHoverBox(){
	var hoverBox = getHoverBox();
	if(hoverBox){
		myLog("Showing");
		hoverBox.style.visibility = "visible";
	}
}

function isHoverBoxVisible(){
	var hoverBox = getHoverBox();
	if(hoverBox.style.visibility == "hidden"){
		return false;
	}
	return true;
}

function toggleHoverBoxDisplay(){
	var hoverBox = getHoverBox();
	if(hoverBox.style.visibility == "hidden"){
		myLog("Showing");
		hoverBox.style.visibility = "visible";
	}
	else{
		myLog("Hiding");
		hoverBox.style.visibility = "hidden";
	}
}

function zoomIn(){
	var command = getCommandButtons().zoomIn;
	myLog(command.src);
	myLog("Zoomming in");
	var mouseDownEvt = createMouseEvt("mousedown");
	var mouseUpEvt = createMouseEvt("mouseup");
	command.dispatchEvent(mouseDownEvt);
	command.dispatchEvent(mouseUpEvt);
}

function zoomOut(){
	var command = getCommandButtons().zoomOut;
	myLog(command.src);
	myLog("Zoomming out");
	clickCommandButton(command);
}

function moveUp(){
	var command = getCommandButtons().up;
	myLog(command.src);
	myLog("MoveUp");
	clickCommandButton(command);
}

function moveDown(){
	var command = getCommandButtons().down;
	myLog(command.src);
	myLog("MoveDown");
	clickCommandButton(command);
}

function moveLeft(){
	var command = getCommandButtons().left;
	myLog(command.src);
	myLog("MoveLeft");
	clickCommandButton(command);
}

function moveRight(){
	var command = getCommandButtons().right;
	myLog(command.src);
	myLog("MoveRight");
	clickCommandButton(command);
}

function searchCommand(){
	if(!isHoverBoxVisible()){
		toggleHoverBoxDisplay();
	}	
	var searchfield = getSearchBox();
	searchfield.focus();
}

function toggleCategoryListDisplay(){
	var command = getCommandButtons().category
	
	myLog("toggleCategoryListDisplay");
	clickCommandButton(command);
}

function clickCommandButton(command){
	var mouseDownEvt = createMouseEvt("mousedown");
	var mouseUpEvt = createMouseEvt("mouseup");
	command.dispatchEvent(mouseDownEvt);
	command.dispatchEvent(mouseUpEvt);
}

function createMouseEvt(evtType){
	var event = document.createEvent("MouseEvents");
	event.initEvent( evtType, true, true );

	return event;
}

function getCommandButtons(){
	if(components.commands != null){
		return components.commands;
	}
	myLog("Setting commands");
	
	var commands = {};
	var hoverBox = getHoverBox();
	var buttonsXPath = "div[5]/table/tr/td/div/img";
	var buttons = $x(buttonsXPath,hoverBox);
	
	if(buttons.length == 0){
		return null;
	}
	
	commands.up = buttons[0];
	commands.down = buttons[1];
	commands.left = buttons[2];
	commands.right = buttons[3];
	commands.zoomIn = buttons[4];
	commands.zoomOut = buttons[5];

	for(i=0;i<6;i++){
		myLog(buttons[i].src);
	}
	
	var categoryXPath = "div[5]/table/tr/td/div[2]/div";
	var result = $x(categoryXPath,hoverBox);
	
	if(result.length == 0){
		return null;
	}
	commands.category = result[0]

	components.commands = commands;
	
	return components.commands;
}

})();