aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristopher Baines <cbaines8@gmail.com>2012-03-27 19:58:50 +0100
committerChristopher Baines <cbaines8@gmail.com>2012-03-27 19:58:50 +0100
commitebfee560786ea52709696b763d5add619c9b33e8 (patch)
treec898f7573ba76bf38f1ff1c9bda63dbd0ec2da2f
parenteb443719666878cedb73c1ab1f7987d5efe66af0 (diff)
downloadsouthampton-university-calendar-applet-ebfee560786ea52709696b763d5add619c9b33e8.tar
southampton-university-calendar-applet-ebfee560786ea52709696b763d5add619c9b33e8.tar.gz
New interface, beginings of trying to make it work as an applet... :(
-rw-r--r--src/net/cbaines/suca/CalendarApplet.java221
-rw-r--r--src/net/cbaines/suca/SotonCalendarFetcher.java57
-rw-r--r--src/net/cbaines/suca/SotonCalendarParser.java24
-rw-r--r--web/SouthamptonUniversityCalendarApplet.jarbin0 -> 2300603 bytes
-rw-r--r--web/applet-fu.js95
-rw-r--r--web/suca.html33
6 files changed, 252 insertions, 178 deletions
diff --git a/src/net/cbaines/suca/CalendarApplet.java b/src/net/cbaines/suca/CalendarApplet.java
index 5569285..816084f 100644
--- a/src/net/cbaines/suca/CalendarApplet.java
+++ b/src/net/cbaines/suca/CalendarApplet.java
@@ -1,7 +1,7 @@
package net.cbaines.suca;
-import java.awt.BorderLayout;
-import java.awt.GridLayout;
+import java.awt.Container;
+import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedWriter;
@@ -11,17 +11,17 @@ import java.io.IOException;
import java.io.StringReader;
import javax.security.auth.login.LoginException;
+import javax.swing.BorderFactory;
+import javax.swing.BoxLayout;
import javax.swing.JApplet;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
+import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JProgressBar;
-import javax.swing.JScrollPane;
-import javax.swing.JTabbedPane;
-import javax.swing.JTextArea;
import javax.swing.JTextField;
import net.fortuna.ical4j.data.CalendarBuilder;
@@ -31,38 +31,22 @@ import net.fortuna.ical4j.model.Calendar;
@SuppressWarnings("serial")
public class CalendarApplet extends JApplet {
- private String calendarCSVString = null;
- private String calendarICALString = null;
+ private CalendarApplet instance;
- private JTabbedPane stageTabbedPane;
+ // The panel holding the stages
+ private Container stages;
- // The panel used for the file fetch stuff
- private JPanel csvFileFetchPanel;
+ // Load University Calendar
+ private JPanel calendarLoadingPanel;
private JTextField usernameTextField;
private JPasswordField passwordTextField;
- private JButton go;
-
- private JProgressBar fetchProgress;
-
- private JButton csvFileSelectorButton;
-
- private JTextArea csvTextArea;
-
- private CalendarApplet instance;
-
- // Panel for the stage controls
-
- private JPanel controlsPanel;
-
- // Panel for the calendar creation
-
- private JPanel calendarCreationPanel;
+ private JButton fetchCalendarButton;
+ private JProgressBar fetchCalendarProgress;
+ // iCal Calendar Creation Options
private JPanel calendarCreationOptions;
- private JProgressBar creationProgress;
- private JButton createCalendarButton;
private JCheckBox mergeDuplicateEventsWithSeperateLocations = new JCheckBox(
"Merge Duplicate Events with Seperate Locations", true);
private JCheckBox showTerms = new JCheckBox("Show Terms", true);
@@ -70,8 +54,13 @@ public class CalendarApplet extends JApplet {
private JCheckBox showSemesterWeeks = new JCheckBox("Show Semester Weeks", true);
private JCheckBox mergeHeaders = new JCheckBox("Merge Headers", false);
- // This is more of a development feature....?
- private JTextArea calendarPreviewTextArea;
+ // Download Calendar
+ private JPanel downloadCalendarPanel;
+ private JButton donwloadCalendarButton;
+
+ // Data
+ private volatile String calendarCSVString = null;
+ private volatile String calendarICALString = null;
public void init() {
// Execute a job on the event-dispatching thread:
@@ -90,82 +79,76 @@ public class CalendarApplet extends JApplet {
void createGUI() {
try {
- stageTabbedPane = new JTabbedPane();
+ stages = getContentPane();
+ stages.setLayout(new BoxLayout(stages, BoxLayout.PAGE_AXIS));
- // Create the first screen
+ // Load University Calendar Stage
- csvFileFetchPanel = new JPanel(new GridLayout(1, 2));
+ calendarLoadingPanel = new JPanel();
+ calendarLoadingPanel.setBorder(BorderFactory.createTitledBorder("Load University Calendar"));
- JTabbedPane csvFileFetchMethodsTabbedPane = new JTabbedPane();
-
- JPanel loginPanel = new JPanel();
- JLabel usernameLabel = new JLabel("Username");
- loginPanel.add(usernameLabel);
+ JPanel usernamePanel = new JPanel();
+ usernamePanel.add(new JLabel("Username"));
usernameTextField = new JTextField(10);
- loginPanel.add(usernameTextField);
+ usernamePanel.add(usernameTextField);
+ calendarLoadingPanel.add(usernamePanel);
- JLabel passwordLabel = new JLabel("Password");
- loginPanel.add(passwordLabel);
+ JPanel passwordPanel = new JPanel();
+ passwordPanel.add(new JLabel("Password"));
passwordTextField = new JPasswordField(10);
- loginPanel.add(passwordTextField);
-
- go = new JButton("Go");
- loginPanel.add(go);
-
- fetchProgress = new JProgressBar();
- fetchProgress.setIndeterminate(true);
- fetchProgress.setVisible(false);
- loginPanel.add(fetchProgress);
+ passwordPanel.add(passwordTextField);
+ calendarLoadingPanel.add(passwordPanel);
- csvFileFetchMethodsTabbedPane.addTab("Download", loginPanel);
-
- JPanel csvFileLoadPanel = new JPanel();
-
- csvFileSelectorButton = new JButton("Load csv file");
- csvFileLoadPanel.add(csvFileSelectorButton);
-
- csvFileFetchMethodsTabbedPane.addTab("Load", csvFileLoadPanel);
- csvFileFetchMethodsTabbedPane.setEnabledAt(1, false);
-
- csvFileFetchPanel.add(csvFileFetchMethodsTabbedPane);
-
- csvTextArea = new JTextArea(100, 100);
- csvFileFetchPanel.add(new JScrollPane(csvTextArea));
-
- go.addActionListener(new ActionListener() {
+ fetchCalendarButton = new JButton("Fetch Calendar");
+ fetchCalendarButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
- go.setEnabled(false);
new FetchThread().start();
}
});
+ calendarLoadingPanel.add(fetchCalendarButton);
+
+ fetchCalendarProgress = new JProgressBar();
+ fetchCalendarProgress.setIndeterminate(false);
+ fetchCalendarProgress.setValue(0);
+ calendarLoadingPanel.add(fetchCalendarProgress);
- stageTabbedPane.addTab("Calendar Fetch", csvFileFetchPanel);
+ stages.add(calendarLoadingPanel);
- // Calendar creation panel
- calendarCreationPanel = new JPanel(new GridLayout(1, 2));
+ // iCal Calendar Creation Options
calendarCreationOptions = new JPanel();
+ calendarCreationOptions.setBorder(BorderFactory.createTitledBorder("Calendar Options"));
- createCalendarButton = new JButton("Create Calendar");
- createCalendarButton.addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent arg0) {
- createCalendarButton.setEnabled(false);
- new CreationThread().start();
- }
- });
- calendarCreationOptions.add(createCalendarButton);
+ calendarCreationOptions.add(mergeDuplicateEventsWithSeperateLocations);
+ calendarCreationOptions.add(showTerms);
+ calendarCreationOptions.add(showSemesters);
+ calendarCreationOptions.add(showSemesterWeeks);
+ calendarCreationOptions.add(mergeHeaders);
+
+ stages.add(calendarCreationOptions);
- JButton saveCalendarButton = new JButton("Save Calendar");
- saveCalendarButton.addActionListener(new ActionListener() {
+ // Calendar Download
+
+ downloadCalendarPanel = new JPanel();
+ downloadCalendarPanel.setBorder(BorderFactory.createTitledBorder("Download Calendar (iCal)"));
+
+ donwloadCalendarButton = new JButton("Download Calendar");
+ donwloadCalendarButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
+ CreationThread creationThread = new CreationThread();
+ creationThread.start();
JFileChooser fc = new JFileChooser();
int returnVal = fc.showSaveDialog(instance); // this = Applet
if (returnVal == JFileChooser.APPROVE_OPTION) {
File file = fc.getSelectedFile();
+ try {
+ creationThread.join();
+ } catch (InterruptedException e1) {
+ e1.printStackTrace();
+ }
try {
BufferedWriter out = new BufferedWriter(new FileWriter(file));
@@ -180,32 +163,10 @@ public class CalendarApplet extends JApplet {
}
});
- calendarCreationOptions.add(saveCalendarButton);
-
- calendarCreationOptions.add(mergeDuplicateEventsWithSeperateLocations);
- calendarCreationOptions.add(showTerms);
- calendarCreationOptions.add(showSemesters);
- calendarCreationOptions.add(showSemesterWeeks);
- calendarCreationOptions.add(mergeHeaders);
- creationProgress = new JProgressBar();
- creationProgress.setIndeterminate(true);
- creationProgress.setVisible(false);
- calendarCreationOptions.add(creationProgress);
+ downloadCalendarPanel.add(donwloadCalendarButton);
- calendarCreationPanel.add(calendarCreationOptions);
+ stages.add(downloadCalendarPanel);
- calendarPreviewTextArea = new JTextArea();
-
- calendarCreationPanel.add(new JScrollPane(calendarPreviewTextArea));
-
- stageTabbedPane.addTab("Calendar Creation", calendarCreationPanel);
-
- controlsPanel = new JPanel();
- controlsPanel.add(new JButton("Previous"));
- controlsPanel.add(new JButton("Next"));
-
- getContentPane().add(stageTabbedPane, BorderLayout.CENTER);
- getContentPane().add(controlsPanel, BorderLayout.SOUTH);
} catch (Exception e) {
e.printStackTrace();
}
@@ -219,35 +180,43 @@ public class CalendarApplet extends JApplet {
@Override
public void run() {
- System.out.println("Starting fetch thread");
+ System.out.println("Start of fetch thread");
+ fetchCalendarButton.setEnabled(false);
+ fetchCalendarProgress.setIndeterminate(true);
+ fetchCalendarProgress.setValue(0);
String csvString;
try {
- fetchProgress.setValue(0);
- fetchProgress.setIndeterminate(true);
- fetchProgress.setVisible(true);
-
csvString = new SotonCalendarFetcher(usernameTextField.getText(), String.valueOf(passwordTextField
.getPassword())).fetchAndParseTimetable();
System.out.println("Finished fetch");
- fetchProgress.setIndeterminate(false);
- fetchProgress.setValue(100);
- fetchProgress.setString("Finished");
-
calendarCSVString = csvString;
- csvTextArea.setText(calendarCSVString);
- go.setEnabled(true);
System.out.println("Finished fetch thread");
+ fetchCalendarButton.setEnabled(true);
+ fetchCalendarProgress.setIndeterminate(false);
+ fetchCalendarProgress.setValue(100);
+
} catch (LoginException e) {
- fetchProgress.setIndeterminate(false);
- fetchProgress.setValue(0);
- fetchProgress.setString("Login Error");
- }
+ fetchCalendarButton.setEnabled(true);
+ fetchCalendarProgress.setIndeterminate(false);
+ fetchCalendarProgress.setValue(0);
+
+ JOptionPane.showMessageDialog(instance,
+ "LoginException: Error logging in, try again, and perhaps also try logging in to SUSSED",
+ "Inane error", JOptionPane.ERROR_MESSAGE);
+ } catch (IOException e) {
+ fetchCalendarButton.setEnabled(true);
+ fetchCalendarProgress.setIndeterminate(false);
+ fetchCalendarProgress.setValue(0);
+ JOptionPane.showMessageDialog(instance,
+ "IOException: Error logging in, try again, and perhaps also try logging in to SUSSED",
+ "Inane error", JOptionPane.ERROR_MESSAGE);
+ }
}
}
@@ -261,10 +230,6 @@ public class CalendarApplet extends JApplet {
public void run() {
System.out.println("Starting creation thread");
- creationProgress.setVisible(true);
- creationProgress.setValue(0);
- creationProgress.setIndeterminate(true);
-
SotonCalendarParser calParser = new SotonCalendarParser();
calParser.setMergeDuplicateEventsWithSeperateLocations(mergeDuplicateEventsWithSeperateLocations
.isSelected());
@@ -277,12 +242,6 @@ public class CalendarApplet extends JApplet {
try {
Calendar calendar = builder.build(new StringReader(calendarCSVString));
calendarICALString = calendar.toString();
- calendarPreviewTextArea.setText(calendarICALString);
- createCalendarButton.setEnabled(true);
-
- creationProgress.setIndeterminate(false);
- creationProgress.setValue(100);
- creationProgress.setString("Finished");
} catch (ParserException e) {
e.printStackTrace();
} catch (IOException e) {
diff --git a/src/net/cbaines/suca/SotonCalendarFetcher.java b/src/net/cbaines/suca/SotonCalendarFetcher.java
index 40a85ff..846faf1 100644
--- a/src/net/cbaines/suca/SotonCalendarFetcher.java
+++ b/src/net/cbaines/suca/SotonCalendarFetcher.java
@@ -30,11 +30,13 @@ public class SotonCalendarFetcher {
this.password = password;
}
- public String fetchAndParseTimetable() throws LoginException {
+ @SuppressWarnings("deprecation")
+ public String fetchAndParseTimetable() throws IOException, LoginException {
DefaultHttpClient httpclient = new DefaultHttpClient();
+ Exception exception = null;
+
try {
- HttpGet httpget = new HttpGet(
- "https://www.adminservices.soton.ac.uk/adminweb/servlet/login");
+ HttpGet httpget = new HttpGet("https://www.adminservices.soton.ac.uk/adminweb/servlet/login");
HttpResponse response = httpclient.execute(httpget);
HttpEntity entity = response.getEntity();
@@ -43,11 +45,7 @@ public class SotonCalendarFetcher {
// response.getStatusLine());
// EntityUtils.consume(entity);
if (entity != null) {
- try {
- entity.consumeContent();
- } catch (IOException e) {
- e.printStackTrace();
- }
+ entity.consumeContent();
}
// System.out.println("Initial set of cookies:");
@@ -60,8 +58,7 @@ public class SotonCalendarFetcher {
}
}
- HttpPost httpost = new HttpPost(
- "https://www.adminservices.soton.ac.uk/adminweb/servlet/login");
+ HttpPost httpost = new HttpPost("https://www.adminservices.soton.ac.uk/adminweb/servlet/login");
List<NameValuePair> nvps = new ArrayList<NameValuePair>();
nvps.add(new BasicNameValuePair("user", username));
@@ -81,11 +78,16 @@ public class SotonCalendarFetcher {
// System.out.println("Login form get: " +
// response.getStatusLine());
// EntityUtils.consume(entity);
- BufferedReader br = new BufferedReader(new InputStreamReader(
- entity.getContent()));
- String line;
- while ((line = br.readLine()) != null) {
- // Log.v(TAG, line);
+ BufferedReader br = new BufferedReader(new InputStreamReader(entity.getContent()));
+ StringBuilder responseBuilder = new StringBuilder();
+ for (String line; (line = br.readLine()) != null;) {
+ responseBuilder.append(line);
+ }
+
+ System.out.println("responseBuilder.length() " + responseBuilder.length());
+
+ if (responseBuilder.length() != 0) {
+ throw new LoginException("Login failed");
}
// System.out.println("Post logon cookies:");
@@ -117,6 +119,7 @@ public class SotonCalendarFetcher {
System.out.println("Second post get: " + response.getStatusLine());
// EntityUtils.consume(entity);
br = new BufferedReader(new InputStreamReader(entity.getContent()));
+ String line;
while ((line = br.readLine()) != null) {
// System.out.println(line);
}
@@ -144,8 +147,7 @@ public class SotonCalendarFetcher {
// Log.v(TAG, line);
}
- httpost = new HttpPost(
- "https://www.adminservices.soton.ac.uk/adminweb/timetables/ttdownload/.csv");
+ httpost = new HttpPost("https://www.adminservices.soton.ac.uk/adminweb/timetables/ttdownload/.csv");
nvps = new ArrayList<NameValuePair>();
nvps.add(new BasicNameValuePair("format", "list"));
@@ -157,19 +159,20 @@ public class SotonCalendarFetcher {
String responseString = IOUtils.toString(entity.getContent());
- if (responseString.contains("Failed Login")) {
- throw new LoginException("Login failed");
- } else {
- return responseString;
- }
+ return responseString;
- } catch (IllegalStateException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
} catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
+ exception = e;
+ } catch (LoginException e) {
+ exception = e;
} finally {
+ if (exception != null) {
+ if (exception instanceof IOException) {
+ throw (IOException) exception;
+ } else if (exception instanceof IOException) {
+ throw (LoginException) exception;
+ }
+ }
// When HttpClient instance is no longer needed,
// shut down the connection manager to ensure
// immediate deallocation of all system resources
diff --git a/src/net/cbaines/suca/SotonCalendarParser.java b/src/net/cbaines/suca/SotonCalendarParser.java
index 8feab9a..38b6ac2 100644
--- a/src/net/cbaines/suca/SotonCalendarParser.java
+++ b/src/net/cbaines/suca/SotonCalendarParser.java
@@ -37,9 +37,9 @@ public class SotonCalendarParser implements CalendarParser {
private boolean mergeHeaders = false;
- private Calendar startYear = UniTermDates.getStartOf(UniTermDates.SEMESTER_1,
- Calendar.getInstance().get(Calendar.YEAR) - 1);
- private Calendar endYear = UniTermDates.getEndOf(UniTermDates.SEMESTER_2, UniTermDates.YEAR_BEGINING_2019);
+ // private Calendar startYear = UniTermDates.getStartOf(UniTermDates.SEMESTER_1,
+ // Calendar.getInstance().get(Calendar.YEAR) - 1);
+ // private Calendar endYear = UniTermDates.getEndOf(UniTermDates.SEMESTER_2, UniTermDates.YEAR_BEGINING_2019);
// private final static String TAG = "SotonCalendarParser";
@@ -296,7 +296,7 @@ public class SotonCalendarParser implements CalendarParser {
handler.startProperty(Property.LOCATION);
handler.propertyValue(event.location);
handler.endProperty(Property.LOCATION);
-
+
// The following infomation should be fetched from the
// Southampton University Map App, through the content
// provider, or from the data.southampton site via a sparqul
@@ -573,19 +573,6 @@ public class SotonCalendarParser implements CalendarParser {
+ cal.get(Calendar.DAY_OF_MONTH) + "/" + (cal.get(Calendar.MONTH) + 1) + "/" + cal.get(Calendar.YEAR));
}
- private static void logDate(String prefix, Date date) {
- Map<Integer, String> daysOfTheWeek = new HashMap<Integer, String>(7);
- daysOfTheWeek.put(Calendar.MONDAY, "Monday");
- daysOfTheWeek.put(Calendar.TUESDAY, "Tuesday");
- daysOfTheWeek.put(Calendar.WEDNESDAY, "Wednesday");
- daysOfTheWeek.put(Calendar.THURSDAY, "Thursday");
- daysOfTheWeek.put(Calendar.FRIDAY, "Friday");
- daysOfTheWeek.put(Calendar.SATURDAY, "Saturday");
- daysOfTheWeek.put(Calendar.SUNDAY, "Sunday");
-
- log(prefix + " " + date.toString());
- }
-
private static void log(String string) {
System.out.println(string);
}
@@ -674,9 +661,6 @@ public class SotonCalendarParser implements CalendarParser {
String location;
String weeks;
- public Event() {
- }
-
public Event(String[] info) {
dayOfWeek = info[0];
startTime = info[1];
diff --git a/web/SouthamptonUniversityCalendarApplet.jar b/web/SouthamptonUniversityCalendarApplet.jar
new file mode 100644
index 0000000..8421c99
--- /dev/null
+++ b/web/SouthamptonUniversityCalendarApplet.jar
Binary files differ
diff --git a/web/applet-fu.js b/web/applet-fu.js
new file mode 100644
index 0000000..092b7d2
--- /dev/null
+++ b/web/applet-fu.js
@@ -0,0 +1,95 @@
+/*
+ * Applet-Fu A Javascript library for cross-browser applet deployment.
+
+ * Copyright (c) 2008, Metamolecular, LLC
+ * All rights reserved.
+ *
+ * http://github.com/rapodaca/applet-fu/tree/master
+ * info@metamolecular.com
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * - Neither the name of Metamolecular, LLC nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+var applet_fu = {
+ run: function(attributes, parameters, minimumVersion, fallbackContent){
+ if (applet_fu.isIE()){
+ applet_fu.openTagIE(attributes)
+ }
+ else{
+ applet_fu.openTagStandard(minimumVersion || '1.4.2');
+ }
+
+ applet_fu.writeAttributes(attributes);
+ applet_fu.writeParameters(parameters);
+ document.write(fallbackContent || 'This content requires Java.');
+ document.write('</object>');
+ },
+
+ /*
+ * Creates the opening object tag for standards-compliant browsers. Requests the minumum JRE version
+ * specified with minimumVersion.
+ */
+ openTagStandard: function(minimumVersion){
+ document.write('<object type="application/x-java-applet;version=' + minimumVersion + '"');
+ },
+
+ /*
+ * Creates the opening object tag for IE using classid and codebase attributes.
+ * If these attributes are not set, EasyApplet will request that the applet be run
+ * with the latest installed JRE, or JDK 1.4, whichever is higher. For more information, see:
+ *
+ * http://java.sun.com/javase/6/webnotes/family-clsid.html
+ * http://java.sun.com/javase/6/docs/technotes/guides/deployment/deployment-guide/autodl-files.html
+ */
+ openTagIE: function(attributes){
+ var classid = attributes['classid'] || "clsid:8AD9C840-044E-11D1-B3E9-00805F499D93"; //use latest installed JRE;
+ var codebase = attributes['codebase'] || "http://java.sun.com/products/plugin/autodl/jinstall-1_4-windows-i586.cab#Version=1,4,0,0"; //download JRE 1.4 if suitable JRE not found;
+
+ document.write('<object classid="' + classid + '" codebase=' + codebase + '"');
+ },
+
+ writeAttributes: function(attributes){
+ for (attribute in attributes){
+ document.write(" ");
+ document.write(attribute + "='" + attributes[attribute] + "'");
+ }
+
+ document.write('>');
+ },
+
+ writeParameters: function(parameters){
+ for (parameter in parameters){
+ document.write("<param name=" + parameter + " value='" + parameters[parameter] + "'>");
+ }
+ },
+
+ isIE: function(){
+ if (navigator == null) return false;
+
+ return navigator.userAgent.match(/MSIE/) != null;
+ }
+}
diff --git a/web/suca.html b/web/suca.html
new file mode 100644
index 0000000..ea11a61
--- /dev/null
+++ b/web/suca.html
@@ -0,0 +1,33 @@
+<html>
+<head>
+
+<title>Southampton University Calendar Applet</title>
+
+<script type="text/javascript" src="applet-fu.js"></script>
+
+</head>
+<body>
+
+<div align="center">
+
+<script type="text/javascript">
+
+applet_fu.run(
+ {'width':'550','height':'320'},
+ {
+ 'archive':'SouthamptonUniversityCalendarApplet.jar',
+ 'code':'net/cbaines/suca/CalendarApplet.class',
+ 'foo':'bar'
+ },
+ '1.4.2',
+ '<h1>No Java</h1>'
+);
+
+</script>
+
+</div>
+
+</body>
+</html>
+
+