views:

339

answers:

2

Hello all. I know that there are lots of examples out there on this, but they all feel a little dated (even the sun docs) so I'm asking here to make sure what I'm doing is up to date. How would I go about talking to javascript from inside a java applet? Something simple like how to call alert() is all I'm looking for. Bonus points for a way to check if the browser has javascript enabled (this applet may be used in a school setting where having javascript turned off is a real possibility). All help is greatly appreciated, thanks in advance...

Code:

import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import netscape.javascript.JSObject;

public class TeamProject extends Applet implements ActionListener, MouseListener {
    char[][] charValues = new char[10][10];
    Table aTable;
    boolean allowUserInput = false;
    Button BtnStart;
    Button randomChangeBtn;
    boolean guessMode;
    JSObject jso;

    public void init() {
     //setup buttons
     BtnStart = new Button("add row/column");
     BtnStart.addActionListener((ActionListener)this); //cast
     randomChangeBtn = new Button("change one value");
     randomChangeBtn.addActionListener((ActionListener)this);
     //add button
     this.add(BtnStart);
     //add image to Image objects
     Image imgO = getImage(getCodeBase(), "images/not.gif");
     Image imgX= getImage(getCodeBase(), "images/cross.gif");
     //setup table
     aTable = new Table(100, 100, 75, 55, 5, 5, imgX, imgO);
     //setBackground(Color.LIGHT_GRAY);
     super.resize(700, 700);
     //add mouse listener
     addMouseListener(this);
     //initially guessMode will be false
     guessMode = false;
     //to talk to javascript
     jso = JSObject.getWindow(this);
    }

    public void paint(Graphics g) {
     g.setColor(Color.black);
     aTable.draw(g);
    }

    //Mouse listener methods
    public void mousePressed (MouseEvent e) {
     if(!guessMode){
      if ((allowUserInput)) { //&&(aTable.isDrawable(e.getX(), e.getY())))
       aTable.swapSquareValue(e.getX(), e.getY());
       repaint();
      }
     } else {
      System.out.println("guessed row = " + e.getY() + " guessed col = " + e.getX());
      aTable.checkGuess(e.getX(), e.getY());
      //repaint();
     }
    }

    public void mouseClicked (MouseEvent e) {}
    public void mouseEntered (MouseEvent e) {}
    public void mouseReleased (MouseEvent e) {}
    public void mouseExited (MouseEvent e) {}

    //Button action listener
    public void actionPerformed(ActionEvent e) {
     if (e.getSource() == BtnStart) {
      aTable.addRow();
      aTable.addColumn();
      this.remove(BtnStart);
      this.add(randomChangeBtn);
      repaint();
     } else if (e.getSource() == randomChangeBtn) {
      //aTable.addRow();
      aTable.randomChangeFunc();
      repaint();
      guessMode = true;
     }
     allowUserInput = true;
     System.out.println(aTable.toString());
    }
}

and my Table class:

import java.awt.*;
import java.util.Random;

public class Table {
    private char[][]values = new char[10][10]; //probably better to use array of integer values(0 or 1)
    Image imgO;
    Image imgX;
    private int Rows;
    private int Columns;
    private int BoxWidth ;
    private int BoxHeight;
    public Point Pos = new Point();

    private int tableHeight;
    private int tableWidth;

    private int changedRow;
    private int changedCol;

    //constructor
    public Table(int x, int y, int width, int height, int col, int rows, Image X, Image O) {
     Rows = rows;
     Columns = col;
     BoxWidth = width;
     BoxHeight = height;
     Pos.x = x;
     Pos.y = y;

     imgX = X;
     imgO = O;

     tableHeight = Rows*BoxHeight;
     tableWidth = Columns*BoxWidth;
     this.setValues();
    }

    //draw table
    public void draw(Graphics g) {
     //draw vertical table lines
     for (int i = 0 ; i <= Columns ; i++)
      g.drawLine(i*BoxWidth + Pos.x, Pos.y, i*BoxWidth + Pos.x, tableHeight+Pos.y);

     //draw horizontal table line
     for(int i = 0 ; i <= Rows ; i++)
      g.drawLine(Pos.x, i*BoxHeight + Pos.y, tableWidth+Pos.x, i*BoxHeight + Pos.y);

     //draw values
     drawValues(g);
    }

    public void swapSquareValue(int x, int y) {
     if (this.isDrawable(x, y)) {
      int col = this.getColumn(x)-1;
      int row = this.getRow(y)-1;

      if(values[row][col] == 'X')
       values[row][col] = 'O';
      else if(values[row][col] == 'O')
       values[row][col] = 'X';
      else
       System.out.println("ERROR SWAPPING SQUARE VALUE");
     } else
      System.out.println("says not drawable");
    }

    public char getValue(int col, int row) {
     return values[row][col];
    }

    //return true if (x,y) is a point in the table
    public boolean isDrawable(int x, int y) {
     if((this.getRow(y)!=-1)||(this.getColumn(x)!=-1))
      return true;
     else
      return false;
    }

    public void addRow() {
     Rows++;
     tableHeight = (Rows*BoxHeight);
     int numOfXs = 0;
     for (int c=0; c < Columns; c++) {
      numOfXs = 0;
      for(int r = 0; r < Rows - 1; r++) {
       if(values[r][c] == 'X'){
        numOfXs++;
        System.out.println("in column " + c + "new x found at " + r + " " + c + ", numOfXs = " + numOfXs);
       }
       if(numOfXs % 2 == 0) {
        values[Rows - 1][c] = 'O';
       } else{
        values[Rows - 1][c] = 'X';
       }
      }//end inner for
      System.out.println("end of column " + c);
     }//end outer for
    }// end function

    public void addColumn() {
     Columns++;
     tableWidth = (Columns*BoxWidth);
     int numOfXs = 0;

     for (int r=0; r < Rows; r++) {
      numOfXs = 0;
      for(int c = 0; c < Columns - 1; c++) {
       if(values[r][c] == 'X') {
        numOfXs++;
        System.out.println("in row " + r + "new x found at " + r + " " + c + ", numOfXs = " + numOfXs);
       }
       if(numOfXs % 2 == 0) {
        values[r][Columns - 1] = 'O';
       }
       else {
        values[r][Columns - 1] = 'X';
       }
      }//end inner for
      System.out.println("end of row " + r);
     }
    }

    //does not add or remove values
    public void setColumn(int col) {
     Columns = col;
     tableWidth = (Columns*BoxWidth);
    }

    //does not add or remove values
    public void setRows(int row) {
     Rows = row;
     tableHeight = (row*BoxHeight);
    }

    public String toString() {
     String ValueString = "Displaying charValues[" + Rows + "][" + Columns + "]\n";
     for (int r=0; r < Rows; r++) {
      for (int c=0; c < Columns; c++) {
       ValueString += (char)values[r][c];
      }
      ValueString += "\n";  //next line
     }
     return ValueString;
    }

    private void drawValues(Graphics g) {
     Point drawPoint = new Point();
     for (int r=0; r < Rows; r++)
      for (int c=0; c < Columns; c++) {
       drawPoint.x = Pos.x+BoxWidth*c;
       drawPoint.y = Pos.y+BoxHeight*r;
       //g.setColor(Color.white);
       //g.fillRect(drawPoint.x+1, drawPoint.y+1, BoxWidth-1, BoxHeight-1);
       if (values[r][c] == 'X') {
        g.drawImage(imgX,drawPoint.x+1, drawPoint.y+1, BoxWidth-1, BoxHeight-1, null);
       } else {
        g.drawImage(imgO,drawPoint.x+1, drawPoint.y+1, BoxWidth-1, BoxHeight-1, null);
       }
       //System.out.print((char)values[r][c]);
      }
     g.setColor(Color.black);
    }

    //fills array with random values
    private void setValues() {
     for (int r=0; r < Rows; r++)
      for (int c=0; c < Columns; c++) {
       values[r][c] = this.randomChar();
      }
    }

    //randomly return 'X' or 'O'
    private char randomChar() {
     char randomValue;
     Random RandomGen = new Random();

     if (RandomGen.nextInt(2)==0)
      randomValue = 'O';
     else
      randomValue ='X';
     return randomValue;
    }

    private int getColumn(int x) {
     int offsetx=0;
     for (int i = 0 ; i < Columns ; i++) {
      offsetx = i*BoxWidth;
      if((x>Pos.x+offsetx)&& (x<Pos.x+offsetx+BoxWidth))
       return i+1;
     }
     return -1;
    }

    private int getRow(int y) {
     int offsety=0;
     for (int i = 0 ; i < Rows ; i++) {
      offsety = i*BoxHeight;
      if((y>Pos.y+offsety)&& (y<Pos.x+offsety+BoxHeight))
       return i+1;
     }
     return -1;
    }

    public void randomChangeFunc() {
     //get random row and column
     Random rand=new Random();

     int randRow = rand.nextInt(Rows);
     int randCol = rand.nextInt(Columns);

     System.out.println("randRow = " + randRow + " randCol = " + randCol);
     /*THIS SHOULD BE HANDLED BY swapSquareValue(randCol,randRow)
     /*BUT GETTING ERRORS (notDrawable). THE FOLLOWING CODE IS A WORK-AROUND
     */
     if(values[randRow][randCol] == 'X')
      values[randRow][randCol] = 'O';
     else if(values[randRow][randCol] == 'O')
      values[randRow][randCol] = 'X';
     else
      System.out.println("ERROR SWAPPING SQUARE VALUE");
     //set globals
     changedRow = randRow;
     changedCol = randCol;
    }

    public void checkGuess(int guessCol, int guessRow){
     int gCol = this.getColumn(guessCol)-1;
     int gRow = this.getRow(guessRow)-1;
     System.out.println("gCol = " + gCol + " gRow = " + gRow);
     if(gCol == changedCol && gRow == changedRow) {
      System.out.println("CORRECT!!!");
     } else
      System.out.println("incorrect :(");
    }
}

Changing my javac command to:

javac -classpath /usr/lib/Java6u1/jre/lib/plugin.jar TeamProject.java

ignores my "Table" class and I get errors where I mention that. Any ideas?

+3  A: 

Look at this article. If you try calling JS from applet on this page it definitely works, because there are js exception after update action from applet :)

import netscape.javascript.JSObject

public void init() { jso = JSObject.getWindow(this); }

 public void actionPerformed(ActionEvent e) {
     if(jso != null )
         try {
                jso.call("updateWebPage", new String[] {txt.getText()});
             }
             catch (Exception ex) {
                 ex.printStackTrace();
             }
 }

EDIT: For the classpath problem you need to add plugin.jar to your classpath which is located in %JAVA_HOME%\jre\lib\plugin.jar

EDIT2:
I think that your problem is that a class Table isn't compiled too:

try javac -classpath /usr/lib/Java6u1/jre/lib/plugin.jar TeamProject.java Table.java or use wildcards like *.java.

Maybe you should consider use IDE like Eclipse or Netbeans to compile and run project instead of struggling with command line tools.

cetnar
using javac -classpath %JAVA_HOME%\jre\lib\plugin.jar TeamProject.java doesn't fix anything, neither does javac -classpath /usr/lib/Java6u1/jre/lib.plugin.jar TeamProject.java
danwoods
Alright! Fixed the problem of finding netscape class but now javac can't find my classes that I wrote outside of the main class file...
danwoods
Well so you have problem with java instalation. Antother aspect is that this code won't compile. There are no class `Table`. Why you import awt package and swing packages? Where this example come from?
cetnar
added all my code
danwoods
A: 

As requested a sample which calls alert on the page it is embedded in (tested in Opera 10.01, FF 3.5.4, IE6).

Note the MAYSCRIPT in the applet tag, this MUST be present to enable java-javascript communication. As per default access to JSObject is disabled due to security reasons.

HTML:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
  "http://www.w3.org/TR/html4/loose.dtd"&gt;
<html>
<head>
  <title>Test</title>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
  <applet code="HelloWWW.class" width="300px" height="100px"  MAYSCRIPT></applet>
</body>
</html>

Java (compile with javac -cp .;[pathtojre]/jre/lib/plugin.jar HelloWWW.java)

import java.awt.*;
import java.applet.*;
import java.awt.event.*;
import netscape.javascript.*;

public class HelloWWW extends Applet implements ActionListener {
  Button runButton;
  public void init() {
    runButton = new Button("Run: alert(\"Hello WWW\")");
    add(runButton);
    runButton.addActionListener(this);
  }
  public void actionPerformed(ActionEvent evt) {
    if (evt.getSource() == runButton) {
      try {
        //get JSOBject
        JSObject jso = JSObject.getWindow(this);
        //call alert with parameter passed as Object array
        jso.call("alert", new Object[]{"Hello WWW"});
      } catch (JSException e) {
        e.printStackTrace();
      }
      runButton.setLabel("Did it!");
      repaint();
    }
  } 
}

Also check Java-to-Javascript Communication and Mozilla Dev: JSObject for further info.

jitter