<html>
  <!--
    This test ensures the correctness of Spatial Navigation (SNav) algorithm over multiple select element.

    * Pre-conditions:
    1) TestRunner support for SNav enable/disable.

    * Navigation steps:
    1) Loads this page, focus goes to "start" automatically.
    2) Focus moves away from select in 4 different directions to neighbor nodes and back.
  -->
  <head>
    <script src="../../resources/js-test-pre.js"></script>
    <script src="resources/spatial-navigation-utils.js"></script>
    <script type="application/javascript">

    var resultMap = [
      ["Down", "start"],
      ["Down", "start"],
      ["Down", "start"],
      ["Down", "8"],
      ["Up", "start"],
      ["Up", "start"],
      ["Up", "start"],
      ["Up", "2"],
      ["Down", "start"],
      ["Right", "6"],
      ["Left", "start"],
      ["Left", "4"],
      ["Right", "start"],
      ["DONE", "DONE"]
    ];

    if (window.testRunner) {
      testRunner.dumpAsText();
      testRunner.setSpatialNavigationEnabled(true);
      testRunner.overridePreference("WebKitTabToLinksPreferenceKey", 1);
      testRunner.waitUntilDone();
    }

    function runTest()
    {
      // starting the test itself: get to a known place.
      document.getElementById("start").focus();

      initTest(resultMap, additionalTest);
    }

    function sendKeyAndCheckOptions(option0, option1, option2, option3)
    {
      shouldBe("gFocusedDocument.getElementById(\"start\").options[0].selected", option0);
      shouldBe("gFocusedDocument.getElementById(\"start\").options[1].selected", option1);
      shouldBe("gFocusedDocument.getElementById(\"start\").options[2].selected", option2);
      shouldBe("gFocusedDocument.getElementById(\"start\").options[3].selected", option3);
    }

    function additionalTest()
    {
      document.getElementById("start").focus();         //move to 1st item
      sendKeyAndCheckOptions("false", "false", "false", "false");
      eventSender.keyDown("downArrow");                 //move to 2nd item
      sendKeyAndCheckOptions("false", "false", "false", "false");
      eventSender.keyDown(" ");                         //nothing should change
      sendKeyAndCheckOptions("false", "true", "false", "false");
      eventSender.keyDown("downArrow");                 //move to 4th item (3rd item is disabled) 
      sendKeyAndCheckOptions("false", "true", "false", "false");
      eventSender.keyDown(" ");                         //nothing should change
      sendKeyAndCheckOptions("false", "true", "false", "true");
      eventSender.keyDown("upArrow");                   //move back to 2nd item
      sendKeyAndCheckOptions("false", "true", "false", "true");
      eventSender.keyDown(" ");                         //noting should change
      sendKeyAndCheckOptions("false", "false", "false", "true");
      eventSender.keyDown("upArrow");                   //move back to 1st item
      sendKeyAndCheckOptions("false", "false", "false", "true");
      eventSender.keyDown("downArrow", ["shiftKey"]);   //shift-down to 2nd item
      sendKeyAndCheckOptions("false", "true", "false", "true");

      testCompleted();
    }

    function testCompleted()
    {
      if (window.testRunner)
        testRunner.notifyDone();
    }

    window.onload = runTest;

    </script>
    <script src="../resources/js-test-post.js"></script>
  </head>
  <body id="some-content" xmlns="http://www.w3.org/1999/xhtml">
    <table style="text-align: left; width: 100%; margin-left: auto; margin-right: auto;" border="1" cellpadding="2" cellspacing="1">
      <tbody>
        <tr>
          <td style="vertical-align: top; text-align: center;"></td>
          <td style="vertical-align: top; text-align: center;"><a id="2" href="a">2</a></td>
          <td style="vertical-align: top; text-align: center;"></td>
        </tr>
        <tr>
          <td style="vertical-align: top; text-align: center;"><a id="4" href="a">4</a></td>
          <td style="vertical-align: top; text-align: center;">
		  <select id="start" multiple><optgroup label="o1"><option>1</option></optgroup><optgroup label="o2"><option>2</option></optgroup><optgroup label="o3"><option disabled>3</option></optgroup><optgroup label="o4"><option>4</option></optgroup>
		  </select></td>
          <td style="vertical-align: top; text-align: center;"><a id="6" href="a">6</a></td>
        </tr>
        <tr>
          <td style="vertical-align: top; text-align: center;"></td>
          <td style="vertical-align: top; text-align: center;"><a id="8" href="a">8</a></td>
          <td style="vertical-align: top; text-align: center;"></td>
        </tr>
      </tbody>
    </table>
    <div id="console"></div>
  </body>
</html>

