mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
949 lines
28 KiB
JavaScript
949 lines
28 KiB
JavaScript
/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
/* ***** BEGIN LICENSE BLOCK *****
|
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
|
*
|
|
* The contents of this file are subject to the Mozilla Public License Version
|
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
|
* the License. You may obtain a copy of the License at
|
|
* http://www.mozilla.org/MPL/
|
|
*
|
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
* for the specific language governing rights and limitations under the
|
|
* License.
|
|
*
|
|
* The Original Code is mozilla.org code.
|
|
*
|
|
* The Initial Developer of the Original Code is
|
|
* Netscape Communications Corporation.
|
|
* Portions created by the Initial Developer are Copyright (C) 1998
|
|
* the Initial Developer. All Rights Reserved.
|
|
*
|
|
* Contributor(s):
|
|
*
|
|
* Alternatively, the contents of this file may be used under the terms of
|
|
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
|
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
|
* of those above. If you wish to allow use of your version of this file only
|
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
|
* use your version of this file under the terms of the MPL, indicate your
|
|
* decision by deleting the provisions above and replace them with the notice
|
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
|
* the provisions above, a recipient may use your version of this file under
|
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
|
*
|
|
* ***** END LICENSE BLOCK ***** */
|
|
|
|
// FOR TESTING XXX
|
|
|
|
function StartCodeTime ( ) {
|
|
CodeTimeInitial = new Date();
|
|
}
|
|
|
|
function EndCodeTime ( str ) {
|
|
var CodeTimeFinal = new Date();
|
|
var diff = CodeTimeFinal.getTime() - CodeTimeInitial.getTime();
|
|
dump("Timing " + str + " took " + diff + " milliseconds.\n");
|
|
}
|
|
|
|
// ************************************************************
|
|
// Initialize stuff
|
|
// ************************************************************
|
|
|
|
haveRead = false;
|
|
currentTime = new Date(); // a new Date object with the current time
|
|
monthShowing = new Date();
|
|
nowShowing = new Date();
|
|
|
|
month_names_internal = new Array("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec");
|
|
|
|
|
|
// the namespace of the RDF literals
|
|
rdf_ns="http://when.com/1999/07/03-appts-rdf#";
|
|
|
|
// find the location of the appointments data - relative URLs don't work (now, anyway)
|
|
|
|
// the filename within the directory of the XUL document
|
|
var RDFRelFileName = 'bug12012.rdf';
|
|
|
|
dump("Getting window.location.href...\n");
|
|
// to get the directory, start with the filename of the XUL document
|
|
var baseURL = window.location.href;
|
|
dump("...done.\n");
|
|
|
|
// XXX Needs three slashes because of file:// URL parsing bug (see Bug 9236)
|
|
//if ((baseURL.indexOf("file:/") != -1) && (baseURL.indexOf("file:///") == -1)) {
|
|
//baseURL = "file:///" + baseURL.substring(6);
|
|
//}
|
|
if (baseURL.indexOf("file:") == 0) {
|
|
baseURL = baseURL.substring(5);
|
|
while (baseURL.charAt(0) == '/') {
|
|
baseURL = baseURL.substring(1);
|
|
}
|
|
baseURL = "file:///" + baseURL;
|
|
}
|
|
|
|
// and take off whatever is after the last "/"
|
|
baseURL = baseURL.substring(0, baseURL.lastIndexOf("/") + 1);
|
|
|
|
// combine these to get the filename for the RDF
|
|
RDFFileName = baseURL + RDFRelFileName;
|
|
appts_resourcename = RDFFileName + "#WhenComAppointmentsRoot";
|
|
|
|
// the rdf service
|
|
RDFService = Components.classes['@mozilla.org/rdf/rdf-service;1'].getService();
|
|
RDFService = RDFService.QueryInterface(Components.interfaces.nsIRDFService);
|
|
|
|
// ************************************************************
|
|
// Event handler for Edit code
|
|
// ************************************************************
|
|
|
|
function ascendToTR (node) {
|
|
var rv = node;
|
|
while ( rv.nodeName.toLowerCase() != "tr" ) {
|
|
rv = rv.parentNode;
|
|
}
|
|
return rv;
|
|
}
|
|
|
|
function handleRClick ( event ) {
|
|
// XXX event.type and event.currentNode and event.button are broken
|
|
var currentNode = ascendToTR(event.target);
|
|
EditApptById(currentNode.getAttribute("id"));
|
|
}
|
|
|
|
// ************************************************************
|
|
// Functions for event handlers (e.g., onclick)
|
|
// ************************************************************
|
|
|
|
function gotoURL( url ) {
|
|
window.content.location = url;
|
|
}
|
|
|
|
function getAddDiv() {
|
|
return document.documentElement.firstChild.nextSibling.nextSibling.firstChild.firstChild;
|
|
}
|
|
|
|
function getScheduleDiv() {
|
|
return document.documentElement.firstChild.nextSibling.nextSibling.firstChild.firstChild.nextSibling;
|
|
}
|
|
|
|
function getPickDiv() {
|
|
return document.documentElement.firstChild.nextSibling.nextSibling.firstChild.firstChild.nextSibling.nextSibling;
|
|
}
|
|
|
|
function buttonDisabled ( number ) {
|
|
// 0 for AddEvent
|
|
// 1 for Schedule
|
|
// 2 for Go To Date
|
|
|
|
var tabTR = document.getElementById("tabsTR");
|
|
tabTR.childNodes.item(0).className = "tab";
|
|
tabTR.childNodes.item(1).className = "tab";
|
|
tabTR.childNodes.item(2).className = "tab";
|
|
tabTR.childNodes.item(number).className = "tab disable";
|
|
|
|
// XXX BUG These two lines cause failure to display
|
|
// setting is on an XULElement
|
|
//tabTR.parentNode.parentNode.style.border="medium solid black";
|
|
//tabTR.parentNode.parentNode.style.border="none";
|
|
|
|
// XXX BUG These two lines cover up most of a shifting bug...
|
|
// Setting is on a table
|
|
tabTR.parentNode.style.border="medium solid black";
|
|
tabTR.parentNode.style.border="none";
|
|
|
|
}
|
|
|
|
function divActive( number ) {
|
|
// 0 for AddEvent
|
|
// 1 for Schedule
|
|
// 2 for Go To Date
|
|
|
|
buttonDisabled(number)
|
|
|
|
// for speed:
|
|
var AddDiv = getAddDiv();
|
|
var ScheduleDiv = getScheduleDiv();
|
|
var PickDiv = getPickDiv()
|
|
|
|
if ( number == 0 ) {
|
|
ScheduleDiv.style.display = "none";
|
|
PickDiv.style.display = "none";
|
|
AddDiv.style.display = "block";
|
|
} else if ( number == 1 ) {
|
|
AddDiv.style.display = "none";
|
|
PickDiv.style.display = "none";
|
|
ScheduleDiv.style.display = "block";
|
|
ShowSchedule();
|
|
} else if ( number == 2 ) {
|
|
AddDiv.style.display = "none";
|
|
ScheduleDiv.style.display = "none";
|
|
PickDiv.style.display = "block";
|
|
ShowPick();
|
|
}
|
|
}
|
|
|
|
function editButtonsActive( number ) {
|
|
// 0 for addbuttons
|
|
// 1 for editbuttons
|
|
|
|
var adddiv = getAddDiv();
|
|
var addbdiv = GetElementWithIdIn("addbuttons", adddiv);
|
|
var edbdiv = GetElementWithIdIn("editbuttons", adddiv);
|
|
|
|
if (number == 0) {
|
|
edbdiv.style.display = "none";
|
|
addbdiv.style.display = "block";
|
|
} else if (number == 1) {
|
|
addbdiv.style.display = "none";
|
|
edbdiv.style.display = "block";
|
|
}
|
|
|
|
}
|
|
|
|
function nextDay() {
|
|
nowShowing.setDate(nowShowing.getDate() + 1);
|
|
ShowSchedule();
|
|
}
|
|
|
|
function nextWeek() {
|
|
nowShowing.setDate(nowShowing.getDate() + 7);
|
|
ShowSchedule();
|
|
}
|
|
|
|
function prevDay() {
|
|
nowShowing.setDate(nowShowing.getDate() - 1);
|
|
ShowSchedule();
|
|
}
|
|
|
|
function prevWeek() {
|
|
nowShowing.setDate(nowShowing.getDate() - 7);
|
|
ShowSchedule();
|
|
}
|
|
|
|
function today() {
|
|
nowShowing = new Date();
|
|
ShowSchedule();
|
|
}
|
|
|
|
/* Date Picker */
|
|
|
|
function nextMonth() {
|
|
monthShowing.setMonth(monthShowing.getMonth() + 1);
|
|
ShowPick();
|
|
}
|
|
|
|
function prevMonth() {
|
|
monthShowing.setMonth(monthShowing.getMonth() - 1);
|
|
ShowPick();
|
|
}
|
|
|
|
function nextYear() {
|
|
monthShowing.setFullYear(monthShowing.getFullYear() + 1);
|
|
ShowPick();
|
|
}
|
|
|
|
function prevYear() {
|
|
monthShowing.setFullYear(monthShowing.getFullYear() - 1);
|
|
ShowPick();
|
|
}
|
|
|
|
function thisMonth() {
|
|
monthShowing = new Date();
|
|
ShowPick();
|
|
}
|
|
|
|
function pickDate( year, month, date ) {
|
|
// the month is 1..12
|
|
nowShowing = new Date(year, month - 1, date);
|
|
divActive(1); // calls ShowSchedule
|
|
}
|
|
|
|
|
|
// ************************************************************
|
|
// Utility functions
|
|
// ************************************************************
|
|
|
|
// XXX Should this be needed?
|
|
|
|
function GetElementWithIdIn ( id, ancestor ) {
|
|
// recursive search for an element with a given id
|
|
if ( ancestor.getAttribute("id") == id ) {
|
|
return ancestor;
|
|
} else { // else shows logic, not really needed because of return
|
|
for (var i = 0; i < ancestor.childNodes.length ; i++ ) {
|
|
// This isn't an official way to use named constants, but
|
|
// Mozilla supports it
|
|
if ( ancestor.childNodes.item(i).nodeType == Node.ELEMENT_NODE ) {
|
|
var rv = GetElementWithIdIn(id, ancestor.childNodes.item(i));
|
|
if (rv != null) {
|
|
return rv; // exits the function here, since we found the target
|
|
}
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
}
|
|
|
|
// ************************************************************
|
|
// The Appointment type
|
|
// ************************************************************
|
|
|
|
function ApptToString () {
|
|
return "[" + String(this.date) + "," + this.title + "]";
|
|
}
|
|
|
|
Appointment.prototype.toString = ApptToString;
|
|
|
|
function Appointment ( date, title, desc, dur, id ) { // used as a constructor
|
|
this.date = date; // date
|
|
this.title = title; // title
|
|
this.desc = desc; // description
|
|
this.dur = dur; // duration (minutes)
|
|
this.id = id; // id (in the RDF and in the table row)
|
|
|
|
// A useful debugging function:
|
|
// XXX If error in string, get silent error:
|
|
//this.toString = new Function('return "[" + String(this.date) + "," + this.title + "]"');
|
|
}
|
|
|
|
function compareAppt ( x , y ) { // for passing to Array::sort
|
|
// should return negative if x<y, 0 if x=y, and positive if x>y
|
|
// Date::getTime returns milliseconds since Jan 1, 1970, so
|
|
return x.date.getTime() - y.date.getTime();
|
|
}
|
|
|
|
// ************************************************************
|
|
// Code used for showing the schedule
|
|
// ************************************************************
|
|
|
|
function getOutputTBody() {
|
|
// get the TBody element for output
|
|
// XXX a hack, since getElementById doesn't work with mixed XUL/HTML, it
|
|
// seems.
|
|
|
|
//return document.documentElement.childNodes.item(2).childNodes.item(1);
|
|
|
|
// hack within a hack, to get around bug 8044
|
|
// for thead:
|
|
return getScheduleDiv().firstChild.nextSibling.firstChild.nextSibling;
|
|
// for no thead:
|
|
// return getScheduleDiv().firstChild.nextSibling.firstChild;
|
|
}
|
|
|
|
function getOutputForDate() {
|
|
// 2, 1, 3
|
|
return getScheduleDiv().firstChild.firstChild.firstChild.nextSibling.nextSibling;
|
|
}
|
|
|
|
function timeString( date ) {
|
|
var minutes = date.getMinutes();
|
|
if (minutes < 10 ) {
|
|
minutes = "0" + minutes;
|
|
}
|
|
var hours = date.getHours();
|
|
if (hours < 12) {
|
|
var suffix = "A";
|
|
} else {
|
|
var suffix = "P";
|
|
}
|
|
if (hours == 0) {
|
|
hours = 12;
|
|
} else if (hours > 12) {
|
|
hours -= 12;
|
|
}
|
|
return hours + ":" + minutes + suffix;
|
|
}
|
|
|
|
function dateString( date ) {
|
|
// month is 0..11
|
|
// ISO-8601 version:
|
|
// return date.getFullYear() + "-" + ( date.getMonth() + 1) + "-" + date.getDate();
|
|
|
|
return month_names_internal[date.getMonth()] + // both 0-based
|
|
" " + date.getDate() + ", " + date.getFullYear();
|
|
}
|
|
|
|
function getAttr(rdf_datasource,service,attr_name) {
|
|
var attr = rdf_datasource.GetTarget(service,
|
|
RDFService.GetResource(rdf_ns + attr_name),
|
|
true);
|
|
if (attr)
|
|
attr = attr.QueryInterface(
|
|
Components.interfaces.nsIRDFLiteral);
|
|
if (attr)
|
|
attr = attr.Value;
|
|
return attr;
|
|
}
|
|
|
|
function ReadAndSort () {
|
|
if ( ! haveRead ) {
|
|
// enumerate all of the flash datasources.
|
|
var enumerator = appts_container.GetElements();
|
|
|
|
// put all the appointments into an array
|
|
allAppts = new Array();
|
|
|
|
try {
|
|
while (enumerator.hasMoreElements()) {
|
|
var service = enumerator.getNext().QueryInterface(
|
|
Components.interfaces.nsIRDFResource);
|
|
|
|
// get the title text
|
|
var title = getAttr(rdf_datasource, service, 'title');
|
|
|
|
// get the description text
|
|
var descrip = getAttr(rdf_datasource, service, 'notes');
|
|
|
|
// get the date, and see if it's for us
|
|
var year = getAttr(rdf_datasource, service, 'year');
|
|
var month = getAttr(rdf_datasource, service, 'month');
|
|
var date = getAttr(rdf_datasource, service, 'date');
|
|
var hour = getAttr(rdf_datasource, service, 'hour');
|
|
var minute = getAttr(rdf_datasource, service, 'minute');
|
|
|
|
// get the full resource URL:
|
|
var theid = service.Value;
|
|
// and use only the fragment identifier:
|
|
theid = theid.substring(theid.lastIndexOf("#") + 1);
|
|
|
|
var duration = getAttr(rdf_datasource, service, 'duration');
|
|
// month is 0..11
|
|
var apptDate = new Date(year, month - 1, date, hour, minute);
|
|
|
|
allAppts[allAppts.length] = new Appointment( apptDate, title, descrip, duration, theid );
|
|
}
|
|
} catch (ex) {
|
|
window.alert("Caught exception [[" + ex + "]]\n");
|
|
}
|
|
haveRead = true;
|
|
}
|
|
|
|
var todaysAppts = new Array();
|
|
|
|
for ( var i = 0 ; i < allAppts.length ; i++ ) {
|
|
var appt = allAppts[i];
|
|
if ( (appt.date.getFullYear() == nowShowing.getFullYear())
|
|
&& (appt.date.getMonth() == nowShowing.getMonth())
|
|
&& (appt.date.getDate() == nowShowing.getDate()) ) {
|
|
|
|
todaysAppts[todaysAppts.length] = appt;
|
|
}
|
|
}
|
|
|
|
// sort todaysAppts using the JavaScript builtin Array::sort(), by
|
|
// providing a sort function
|
|
todaysAppts.sort( compareAppt );
|
|
|
|
return todaysAppts;
|
|
}
|
|
|
|
function ShowSchedule() {
|
|
// Get the nodes where we will output
|
|
var outTB = getOutputTBody();
|
|
var outDate = getOutputForDate();
|
|
|
|
// Remove all its existing children, since we'll rewrite them
|
|
while (outTB.hasChildNodes() ) {
|
|
outTB.removeChild(outTB.firstChild);
|
|
}
|
|
while (outDate.hasChildNodes() ) {
|
|
outDate.removeChild(outDate.firstChild);
|
|
}
|
|
|
|
// Write the date at the top
|
|
outDate.appendChild(document.createTextNode(dateString(nowShowing)));
|
|
|
|
// and write the appointments to the table...
|
|
|
|
// XXX Hack: get around insertRow() bug.
|
|
var newrow = outTB.insertRow(outTB.rows.length);
|
|
|
|
// Get the appointments for today, already sorted, from some kind of input
|
|
// this is an Array of Appointment
|
|
|
|
var todaysAppts = ReadAndSort();
|
|
|
|
for ( var i = 0 ; i < todaysAppts.length ; i++ ) {
|
|
var appt = todaysAppts[i];
|
|
|
|
// add the appointment to the list:
|
|
|
|
var newrow = outTB.insertRow(outTB.rows.length);
|
|
|
|
// set up event handling
|
|
newrow.setAttribute("id", appt.id);
|
|
// XXX extra param shouldn't be needed
|
|
newrow.addEventListener("click", handleRClick, false, false);
|
|
|
|
// XXX Hack: get around insertCell() bug by switching order.
|
|
var titlecell = newrow.insertCell(1);
|
|
var timecell = newrow.insertCell(0);
|
|
timecell.appendChild(document.createTextNode(timeString(appt.date)));
|
|
titlecell.appendChild(document.createTextNode(appt.title));
|
|
}
|
|
}
|
|
|
|
// ************************************************************
|
|
// Code used for the Goto date function
|
|
// ************************************************************
|
|
|
|
// monthShowing holds Year and Month for current Calendar
|
|
|
|
function monthString( date ) {
|
|
// ISO-8601 format
|
|
// return date.getFullYear() + "-" + ( date.getMonth() + 1);
|
|
return month_names_internal[date.getMonth()] + // both 0-based
|
|
" " + date.getFullYear();
|
|
}
|
|
|
|
function ShowPick() {
|
|
var pickDiv = getPickDiv(); // for speed
|
|
// StartCodeTime();
|
|
var outCal = GetElementWithIdIn("calendar", pickDiv);
|
|
var outDate = GetElementWithIdIn("MonthOutput", pickDiv);
|
|
// EndCodeTime("two runs of GetElementWithIdIn");
|
|
|
|
// StartCodeTime();
|
|
// Remove all existing children, since we'll rewrite them
|
|
while (outCal.hasChildNodes() ) {
|
|
outCal.removeChild(outCal.firstChild);
|
|
}
|
|
while (outDate.hasChildNodes() ) {
|
|
outDate.removeChild(outDate.firstChild);
|
|
}
|
|
// EndCodeTime("removing existing children");
|
|
|
|
// StartCodeTime();
|
|
// Write the month at the top
|
|
outDate.appendChild(document.createTextNode(monthString(monthShowing)));
|
|
// EndCodeTime("initial stuff");
|
|
|
|
// and write the calendar to the table...
|
|
|
|
// StartCodeTime();
|
|
// XXX Hack: get around insertRow() bug.
|
|
var myrow = outCal.insertRow(0);
|
|
// EndCodeTime("initial stuff");
|
|
|
|
// make room before the first day, which starts on a strange day of the week
|
|
// note that getDay(), 0=Sunday and 6=Saturday
|
|
|
|
// StartCodeTime();
|
|
var curDay = new Date(monthShowing); // get the month we want to show
|
|
curDay.setDate(1); // start with the first day of the month
|
|
// EndCodeTime("setting curDay");
|
|
|
|
// StartCodeTime();
|
|
myrow = outCal.insertRow(outCal.rows.length);
|
|
var junkcell = myrow.insertCell(0); // XXX Bug in insertCell
|
|
for (var i = 0 ; i < curDay.getDay() ; i++ ) {
|
|
myrow.insertCell(myrow.cells.length);
|
|
}
|
|
// EndCodeTime("writing extra cells");
|
|
|
|
// StartCodeTime();
|
|
var mycell;
|
|
var targMonth = monthShowing.getMonth(); // for speed - saves 30ms
|
|
// for speed:
|
|
var testNowShowing = (
|
|
( monthShowing.getFullYear() == nowShowing.getFullYear()) &&
|
|
( monthShowing.getMonth() == nowShowing.getMonth()) );
|
|
var testCurrentTime = (
|
|
( monthShowing.getFullYear() == currentTime.getFullYear()) &&
|
|
( monthShowing.getMonth() == currentTime.getMonth()) );
|
|
|
|
while ( curDay.getMonth() == targMonth ) {
|
|
if ( ( curDay.getDay() == 0) && (curDay.getDate() != 1) ) {
|
|
// if it's Sunday, and not the 1st of the month
|
|
// then add a new row
|
|
myrow = outCal.insertRow(outCal.rows.length);
|
|
junkcell = myrow.insertCell(0); // XXX Bug in insertCell
|
|
}
|
|
mycell = myrow.insertCell( myrow.cells.length );
|
|
// put the number of the current date in the cell
|
|
mycell.appendChild( document.createTextNode( curDay.getDate() ) );
|
|
// and set the onClick handler
|
|
mycell.setAttribute("onclick", "pickDate(" + curDay.getFullYear()
|
|
+ "," + (curDay.getMonth() + 1)
|
|
+ "," + curDay.getDate()
|
|
+ ")");
|
|
// and set the class
|
|
var classNm = "caldate";
|
|
if ( testNowShowing && ( curDay.getDate() == nowShowing.getDate())) {
|
|
classNm += " nowshowing";
|
|
}
|
|
if ( testCurrentTime && ( curDay.getDate() == currentTime.getDate())) {
|
|
classNm += " today";
|
|
}
|
|
mycell.setAttribute("class", classNm);
|
|
// and loop...
|
|
curDay.setDate(curDay.getDate() + 1);
|
|
}
|
|
// EndCodeTime("writing the days");
|
|
}
|
|
|
|
|
|
// ************************************************************
|
|
// Code used for Adding to the data
|
|
// ************************************************************
|
|
|
|
function makeAssert ( source, data, name ) {
|
|
var target = RDFService.GetLiteral(data);
|
|
var arc = RDFService.GetResource(rdf_ns + name);
|
|
rdf_datasource.Assert(source, arc, target, true);
|
|
}
|
|
|
|
function SendBackToSource( appt ) {
|
|
|
|
// make a resource for the new appointment
|
|
|
|
// These four all write, but only first appt works
|
|
// var sourceNode = RDFService.GetResource("http://www.w3.org/1999/02/22-rdf-syntax-ns#Description");
|
|
// var sourceNode = RDFService.GetResource("");
|
|
// var sourceNode = RDFService.GetResource("aoeuidhtns");
|
|
// var sourceNode = RDFService.GetResource("http://when.com/aoeuidhtns#");
|
|
|
|
// milliseconds since 1970-01-01 00:00 should be a good enough
|
|
// unique identifier (creation time of appt)
|
|
var sourceNode
|
|
= RDFService.GetResource(RDFFileName +"#" + appt.id);
|
|
|
|
// create literals and assert a relationship to the new appointment
|
|
// for each piece of data
|
|
|
|
makeAssert( sourceNode, appt.date.getFullYear(), 'year');
|
|
makeAssert( sourceNode, appt.date.getMonth() + 1, 'month'); // month is 0..1 in the date structure
|
|
makeAssert( sourceNode, appt.date.getDate(), 'date');
|
|
makeAssert( sourceNode, appt.date.getHours(), 'hour');
|
|
makeAssert( sourceNode, appt.date.getMinutes(), 'minute');
|
|
makeAssert( sourceNode, appt.title, 'title');
|
|
makeAssert( sourceNode, appt.desc, 'notes');
|
|
makeAssert( sourceNode, appt.dur, 'duration');
|
|
|
|
// connect the new appointment to the datasource
|
|
|
|
appts_container.AppendElement( sourceNode );
|
|
|
|
// write the datasource back to disk
|
|
|
|
try {
|
|
rdf_remote_datasource.Flush(); // must be a RemoteDataSource, after 1999-06-23
|
|
} catch (ex) {
|
|
window.alert("Caught exception [[" + ex + "]] in Flush().\n");
|
|
}
|
|
|
|
}
|
|
|
|
function Add( appt ) {
|
|
|
|
// Add it to our internal data -- note that we don't show it!
|
|
allAppts[allAppts.length] = appt;
|
|
|
|
// and add it to the external data
|
|
SendBackToSource( appt );
|
|
|
|
}
|
|
|
|
function ResetAddFormTo( year, month, date, hrs, min, durhrs, durmin, title, notes) {
|
|
var addDiv = getAddDiv(); // for speed
|
|
|
|
var yearselect = GetElementWithIdIn("addyear", addDiv );
|
|
var monthselect = GetElementWithIdIn("addmonth", addDiv );
|
|
var dayselect = GetElementWithIdIn("addday", addDiv );
|
|
var hourselect = GetElementWithIdIn("addtimehrs", addDiv );
|
|
var minselect = GetElementWithIdIn("addtimemin", addDiv );
|
|
var durhourselect = GetElementWithIdIn("adddurhrs", addDiv );
|
|
var durminselect = GetElementWithIdIn("adddurmin", addDiv );
|
|
|
|
var titleInput = GetElementWithIdIn("addtitle", addDiv );
|
|
var notesInput = GetElementWithIdIn("addnotes", addDiv );
|
|
|
|
if (yearselect != null) { // "if (yearselect)" works too
|
|
// Subtract the value of the first year in the list to set
|
|
// selectedIndex. JavaScript converts the string value to a number.
|
|
yearselect.selectedIndex =
|
|
year - yearselect.options.item(0).value;
|
|
} else {
|
|
window.alert("Hit a null.");
|
|
}
|
|
|
|
if (monthselect != null) {
|
|
// selectedIndex 0 based, so subtract one
|
|
monthselect.selectedIndex = month - 1;
|
|
} else {
|
|
window.alert("Hit a null.");
|
|
}
|
|
|
|
if (dayselect != null) {
|
|
// selectedIndex 0 based, so subtract one
|
|
dayselect.selectedIndex = date - 1;
|
|
} else {
|
|
window.alert("Hit a null.");
|
|
}
|
|
|
|
if (hourselect != null) {
|
|
// both 0 based
|
|
hourselect.selectedIndex = hrs ;
|
|
} else {
|
|
window.alert("Hit a null.");
|
|
}
|
|
|
|
if (minselect != null) {
|
|
minselect.selectedIndex = Math.round(min / 5);
|
|
} else {
|
|
window.alert("Hit a null.");
|
|
}
|
|
|
|
if (durhourselect != null) {
|
|
durhourselect.selectedIndex = durhrs;
|
|
} else {
|
|
window.alert("Hit a null.");
|
|
}
|
|
|
|
if (durminselect != null) {
|
|
durminselect.selectedIndex = Math.round(durmin / 5);
|
|
} else {
|
|
window.alert("Hit a null.");
|
|
}
|
|
|
|
if (titleInput != null) {
|
|
if ( title == null) {
|
|
title = "";
|
|
}
|
|
titleInput.value = title;
|
|
} else {
|
|
window.alert("Hit a null.");
|
|
}
|
|
|
|
if (notesInput != null) {
|
|
if ( notes == null) {
|
|
notes = "";
|
|
}
|
|
notesInput.value = notes;
|
|
} else {
|
|
window.alert("Hit a null.");
|
|
}
|
|
|
|
}
|
|
|
|
function ResetAddForm() {
|
|
editButtonsActive(0);
|
|
ResetAddFormTo( nowShowing.getFullYear(),
|
|
nowShowing.getMonth() + 1,
|
|
nowShowing.getDate(),
|
|
nowShowing.getHours() + 1, // upcoming hour
|
|
0, // minutes
|
|
0, // duration hours
|
|
0, // duration minutes
|
|
"", // title
|
|
""); // notes
|
|
}
|
|
|
|
function SubmitAddForm() {
|
|
var addDiv = getAddDiv(); // for speed
|
|
|
|
var title = GetElementWithIdIn("addtitle", addDiv );
|
|
var years = GetElementWithIdIn("addyear", addDiv );
|
|
var months = GetElementWithIdIn("addmonth", addDiv );
|
|
var days = GetElementWithIdIn("addday", addDiv );
|
|
var timehrs = GetElementWithIdIn("addtimehrs", addDiv );
|
|
var timemin = GetElementWithIdIn("addtimemin", addDiv );
|
|
var durhrs = GetElementWithIdIn("adddurhrs", addDiv );
|
|
var durmin = GetElementWithIdIn("adddurmin", addDiv );
|
|
var notes = GetElementWithIdIn("addnotes", addDiv );
|
|
|
|
if ( ( title == null ) ||
|
|
( years == null ) ||
|
|
( months == null ) ||
|
|
( days == null ) ||
|
|
( timehrs == null ) ||
|
|
( timemin == null ) ||
|
|
( durhrs == null ) ||
|
|
( durmin == null ) ||
|
|
( notes == null ) ) {
|
|
window.alert("Something is null. Addition failed.\n");
|
|
} else {
|
|
// months go 0..11
|
|
var apptid = "appt" + (new Date().getTime());
|
|
Add( new Appointment( new Date ( years.value, months.value - 1,
|
|
days.value, timehrs.value,
|
|
timemin.value ),
|
|
title.value,
|
|
notes.value,
|
|
(durhrs.value * 60) + (durmin.value * 1),
|
|
apptid));
|
|
// ResetAddForm();
|
|
divActive(1);
|
|
}
|
|
}
|
|
|
|
// ************************************************************
|
|
// Edit code, which uses add form
|
|
// ************************************************************
|
|
|
|
function getApptById( id ) {
|
|
for (var i = 0 ; i < allAppts.length ; i++ ) {
|
|
if ( allAppts[i].id == id ) {
|
|
return allAppts[i];
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
function removeApptById ( id ) {
|
|
for (var i = 0 ; i < allAppts.length ; i++ ) {
|
|
if ( allAppts[i].id == id ) {
|
|
// Remove from list
|
|
allAppts[i] = allAppts[allAppts.length - 1];
|
|
allAppts[allAppts.length - 1] = null;
|
|
allAppts.length -= 1;
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
function EditApptById( theid ) {
|
|
idEditing = theid; // global variable
|
|
|
|
var apptEditing = getApptById( idEditing );
|
|
if ( apptEditing == null) {
|
|
window.alert("Null appointment. Something's wrong.\n");
|
|
return;
|
|
}
|
|
divActive(0); // XXX This should come later, but...
|
|
editButtonsActive(1);
|
|
ResetAddFormTo( apptEditing.date.getFullYear(),
|
|
apptEditing.date.getMonth() + 1,
|
|
apptEditing.date.getDate(),
|
|
apptEditing.date.getHours(),
|
|
apptEditing.date.getMinutes(),
|
|
Math.floor(apptEditing.dur / 60),
|
|
apptEditing.dur % 60,
|
|
apptEditing.title,
|
|
apptEditing.desc );
|
|
}
|
|
|
|
function getAttrLiteral(rdf_datasource,service,attr_name) {
|
|
var attr = rdf_datasource.GetTarget(service,
|
|
RDFService.GetResource(rdf_ns + attr_name),
|
|
true);
|
|
if (attr)
|
|
attr = attr.QueryInterface(
|
|
Components.interfaces.nsIRDFLiteral);
|
|
return attr;
|
|
}
|
|
|
|
function makeUnAssert ( rdf_datasource, resource, name ) {
|
|
var target = getAttrLiteral(rdf_datasource, resource, name);
|
|
var data = getAttr(rdf_datasource, resource, name); // function above
|
|
var arc = RDFService.GetResource(rdf_ns + name);
|
|
rdf_datasource.Unassert(resource, arc, target);
|
|
}
|
|
|
|
function DeleteEditing() {
|
|
// delete from our list:
|
|
removeApptById(idEditing);
|
|
|
|
// delete from the data source
|
|
var sourceNode = RDFService.GetResource(RDFFileName +"#" + idEditing);
|
|
appts_container.RemoveElement( sourceNode, true );
|
|
|
|
// Need to unassert all of sourceNode's relationships
|
|
makeUnAssert(rdf_datasource, sourceNode, 'year');
|
|
makeUnAssert(rdf_datasource, sourceNode, 'month');
|
|
makeUnAssert(rdf_datasource, sourceNode, 'date');
|
|
makeUnAssert(rdf_datasource, sourceNode, 'hour');
|
|
makeUnAssert(rdf_datasource, sourceNode, 'minute');
|
|
makeUnAssert(rdf_datasource, sourceNode, 'title');
|
|
makeUnAssert(rdf_datasource, sourceNode, 'notes');
|
|
makeUnAssert(rdf_datasource, sourceNode, 'duration');
|
|
|
|
try {
|
|
rdf_remote_datasource.Flush(); // must be a RemoteDataSource, after 1999-06-23
|
|
} catch (ex) {
|
|
window.alert("Caught exception [[" + ex + "]] in Flush().\n");
|
|
}
|
|
|
|
}
|
|
|
|
function EditFormSubmit() {
|
|
DeleteEditing();
|
|
SubmitAddForm();
|
|
divActive(1);
|
|
}
|
|
|
|
function EditFormDelete() {
|
|
DeleteEditing();
|
|
divActive(1);
|
|
}
|
|
|
|
function EditFormCancel() {
|
|
divActive(1);
|
|
}
|
|
|
|
// ************************************************************
|
|
// Startup Code
|
|
// ************************************************************
|
|
|
|
function Init()
|
|
{
|
|
// Initialize the Sidebar
|
|
|
|
// Install all the datasources named in the Flash Registry into
|
|
// the tree control. Datasources are listed as members of the
|
|
// NC:FlashDataSources sequence, and are loaded in the order that
|
|
// they appear in that sequence.
|
|
try {
|
|
// First try to construct a new one and load it
|
|
// synchronously. nsIRDFService::GetDataSource() loads RDF/XML
|
|
// asynchronously by default.
|
|
rdf_datasource = Components.classes['@mozilla.org/rdf/datasource;1?name=xml-datasource'].createInstance();
|
|
rdf_datasource = rdf_datasource.QueryInterface(Components.interfaces.nsIRDFDataSource);
|
|
|
|
rdf_remote_datasource = rdf_datasource.QueryInterface(Components.interfaces.nsIRDFRemoteDataSource);
|
|
rdf_remote_datasource.Init(RDFFileName); // this will throw if it's already been opened and registered.
|
|
|
|
dump("Reading datasource synchronously.\n");
|
|
// read it in synchronously.
|
|
rdf_remote_datasource.Refresh(true);
|
|
}
|
|
catch (ex) {
|
|
// if we get here, then the RDF/XML has been opened and read
|
|
// once. We just need to grab the datasource.
|
|
dump("Datasource already read. Grabbing.\n");
|
|
rdf_datasource = RDFService.GetDataSource(RDFFileName);
|
|
}
|
|
|
|
// Create a 'container' wrapper around the appts_resourcename
|
|
// resource so we can use some utility routines that make access a
|
|
// bit easier.
|
|
// NOT var, so it's global
|
|
appts_container = Components.classes['@mozilla.org/rdf/container;1'].createInstance();
|
|
appts_container = appts_container.QueryInterface(Components.interfaces.nsIRDFContainer);
|
|
|
|
appts_resource = RDFService.GetResource(appts_resourcename);
|
|
appts_container.Init(rdf_datasource, appts_resource);
|
|
}
|
|
|
|
function Boot() {
|
|
|
|
if (document.getElementById("ApptsWindow")) {
|
|
dump("Calling init:\n");
|
|
Init();
|
|
|
|
// XXX Bug 9136 - this doesn't work when form is hidden.
|
|
// ResetAddForm();
|
|
|
|
// ShowSchedule();
|
|
dump("Calling divActive(1):\n");
|
|
divActive(1);
|
|
dump("Done initializing.\n");
|
|
// and let events take things from there...
|
|
} else {
|
|
setTimeout("Boot()", 0);
|
|
}
|
|
}
|