gecko-dev/mailnews/base/resources/content/subscribe.js

483 lines
12 KiB
JavaScript
Raw Normal View History

2000-03-21 03:16:39 +00:00
var gSubscribeTree = null;
var okCallback = null;
2000-03-21 03:16:39 +00:00
var gChangeTable = {};
var gServerURI = null;
var gSubscribableServer = null;
var gStatusBar = null;
var gNameField = null;
2000-05-12 06:43:11 +00:00
var gFolderDelimiter = ".";
var gStatusFeedback = new nsMsgStatusFeedback;
// the rdf service
var RDF = '@mozilla.org/rdf/rdf-service;1'
RDF = Components.classes[RDF].getService();
RDF = RDF.QueryInterface(Components.interfaces.nsIRDFService);
var subscribeDS = RDF.GetDataSource("rdf:subscribe");
2000-09-18 21:49:17 +00:00
// used for caching the tree children (in typedown)
var lastTreeChildrenValue = null;
var lastTreeChildren = null;
function goDoCommand()
{
}
function Stop()
{
//dump("Stop()\n")
if (gSubscribableServer) {
gSubscribableServer.stopPopulating(msgWindow);
}
}
var Bundle = srGetStrBundle("chrome://messenger/locale/subscribe.properties");
function SetServerTypeSpecificTextValues()
{
if (!gServerURI) return;
var serverType = GetMsgFolderFromUri(gServerURI).server.type;
//set the server specific ui elements
var element = document.getElementById("foldertextlabel");
var stringName = "foldertextfor-" + serverType;
var stringval = Bundle.GetStringFromName(stringName);
element.setAttribute('value',stringval);
stringName = "foldersheaderfor-" + serverType;
stringval = Bundle.GetStringFromName(stringName);
element = document.getElementById("foldersheaderlabel");
element.setAttribute('value',stringval);
//set the delimiter
try {
gFolderDelimiter = gSubscribableServer.delimiter;
}
catch (ex) {
//dump(ex + "\n");
gFolderDelimiter = ".";
}
}
function onServerClick(event)
{
var item = event.target;
gServerURI = item.id;
//dump("gServerURI="+gServerURI+"\n");
SetUpTree(false);
SetServerTypeSpecificTextValues();
}
function SetUpServerMenu()
{
//dump("SetUpServerMenu()\n");
var serverMenu = document.getElementById("serverMenu");
var menuitems = serverMenu.getElementsByAttribute("id", gServerURI);
try {
//dump("gServerURI="+gServerURI+"\n");
//dump("menuitems="+menuitems+"\n");
//dump("menuitems[0]="+menuitems[0]+"\n");
//dump("serverMenu="+serverMenu+"\n");
serverMenu.selectedItem = menuitems[0];
}
catch (ex) {
//dump("failed to set the selected server: " + ex + "\n");
}
SetServerTypeSpecificTextValues();
}
var MySubscribeListener = {
OnDonePopulating: function() {
gStatusFeedback.showProgress(100);
gStatusFeedback.showStatusString(Bundle.GetStringFromName("doneString"));
gStatusBar.setAttribute("mode","normal");
// only re-root the tree, if it is null.
// otherwise, we are in here because we are populating
// a part of the tree
var refValue = gSubscribeTree.getAttribute('ref');
//dump("ref = " + refValue + refValue.length + "\n");
if (refValue == "null") {
//dump("root subscribe tree at: "+ gServerURI +"\n");
gSubscribeTree.database.AddDataSource(subscribeDS);
gSubscribeTree.setAttribute('ref',gServerURI);
}
}
};
function SetUpTree(forceToServer)
2000-03-28 04:03:25 +00:00
{
//dump("SetUpTree()\n");
2000-09-18 21:49:17 +00:00
// forget the cached tree children
lastTreeChildrenValue = null;
lastTreeChildren = null;
gStatusBar = document.getElementById('statusbar-icon');
if (!gServerURI) return;
var folder = GetMsgFolderFromUri(gServerURI);
var server = folder.server;
try {
gSubscribableServer = server.QueryInterface(Components.interfaces.nsISubscribableServer);
gSubscribeTree.setAttribute('ref',null);
2000-03-28 04:03:25 +00:00
// clear out the text field when switching server
gNameField.setAttribute('value',"");
gSubscribeTree.database.RemoveDataSource(subscribeDS);
gSubscribableServer.subscribeListener = MySubscribeListener;
gStatusFeedback.showProgress(0);
gStatusFeedback.showStatusString(Bundle.GetStringFromName("pleaseWaitString"));
gStatusBar.setAttribute("mode","undetermined");
gSubscribableServer.startPopulating(msgWindow, forceToServer);
}
catch (ex) {
//dump("failed to populate subscribe ds: " + ex + "\n");
}
2000-03-28 04:03:25 +00:00
}
function SubscribeOnLoad()
{
//dump("SubscribeOnLoad()\n");
2000-03-28 04:03:25 +00:00
gSubscribeTree = document.getElementById('subscribetree');
gNameField = document.getElementById('namefield');
msgWindow = Components.classes[msgWindowContractID].createInstance(Components.interfaces.nsIMsgWindow);
msgWindow.statusFeedback = gStatusFeedback;
msgWindow.SetDOMWindow(window);
doSetOKCancel(subscribeOK,subscribeCancel);
// look in arguments[0] for parameters
if (window.arguments && window.arguments[0]) {
if ( window.arguments[0].okCallback ) {
top.okCallback = window.arguments[0].okCallback;
}
}
gServerURI = null;
if (window.arguments[0].preselectedURI) {
var uri = window.arguments[0].preselectedURI;
//dump("subscribe: got a uri," + uri + "\n");
2000-09-18 21:44:54 +00:00
var folder = GetMsgFolderFromUri(uri);
//dump("folder="+folder+"\n");
//dump("folder.server="+folder.server+"\n");
try {
gSubscribableServer = folder.server.QueryInterface(Components.interfaces.nsISubscribableServer);
gServerURI = folder.server.serverURI;
}
catch (ex) {
//dump("not a subscribable server\n");
gSubscribableServer = null;
gServerURI = null;
}
}
if (!gServerURI) {
//dump("subscribe: no uri\n");
//dump("xxx todo: use the default news server. right now, I'm just using the first server\n");
var serverMenu = document.getElementById("serverMenu");
var menuitems = serverMenu.getElementsByTagName("menuitem");
if (menuitems.length > 1) {
gServerURI = menuitems[1].id;
}
else {
//dump("xxx todo none of your servers are subscribable\n");
//dump("xxx todo fix this by disabling subscribe if no subscribable server or, add a CREATE SERVER button, like in 4.x\n");
return;
}
}
SetUpServerMenu();
SetUpTree(false);
gNameField.focus();
}
function subscribeOK()
{
//dump("in subscribeOK()\n")
if (top.okCallback) {
top.okCallback(top.gChangeTable);
}
Stop();
if (gSubscribableServer) {
gSubscribableServer.subscribeCleanup();
}
return true;
}
function subscribeCancel()
{
//dump("in subscribeCancel()\n");
Stop();
if (gSubscribableServer) {
gSubscribableServer.subscribeCleanup();
}
return true;
}
function SetState(name,state)
{
//dump("SetState(" + name + "," + state + ")\n");
var changed = gSubscribableServer.setState(name, state);
if (changed) {
StateChanged(name,state);
2000-03-21 01:03:25 +00:00
}
}
function changeTableRecord(server, name, state) {
this.server = server;
this.name = name;
this.state = state;
}
function StateChanged(name,state)
2000-03-21 03:16:39 +00:00
{
if (gServerURI in gChangeTable) {
if (name in gChangeTable[gServerURI]) {
var oldValue = gChangeTable[gServerURI][name];
if (oldValue != state)
delete gChangeTable[gServerURI][name];
}
else {
gChangeTable[gServerURI][name] = state;
}
}
else {
gChangeTable[gServerURI] = {};
gChangeTable[gServerURI][name] = state;
}
2000-03-21 03:16:39 +00:00
}
2000-03-21 01:03:25 +00:00
function SetSubscribeState(state)
{
try {
2000-03-21 03:16:39 +00:00
var groupList = gSubscribeTree.selectedItems;
for (var i=0;i<groupList.length;i++) {
var group = groupList[i];
var name = group.getAttribute('name');
SetState(name,state);
2000-03-21 01:03:25 +00:00
}
}
catch (ex) {
//dump("SetSubscribedState failed: " + ex + "\n");
}
}
function ReverseStateFromNode(node)
{
var state;
if (node.getAttribute('Subscribed') == "true") {
state = false;
}
else {
state = true;
}
var uri = node.getAttribute('id');
var name = node.getAttribute('name');
SetState(name, state);
}
function SubscribeOnClick(event)
{
var t = event.originalTarget;
2000-09-07 08:17:32 +00:00
if (event.detail == 2) {
2000-09-07 08:17:32 +00:00
ReverseStateFromNode(t.parentNode.parentNode);
}
else {
2000-09-07 08:17:32 +00:00
if (t.getAttribute('twisty') == 'true') {
var treeitem = t.parentNode.parentNode.parentNode;
var open = treeitem.getAttribute('open');
if(open == "true") {
var uri = treeitem.getAttribute("id");
//dump("do twisty for " + uri + "\n");
gStatusFeedback.showProgress(0);
gStatusFeedback.showStatusString(Bundle.GetStringFromName("pleaseWaitString"));
gStatusBar.setAttribute("mode","undetermined");
gSubscribableServer.startPopulatingWithUri(msgWindow, true /* force to server */, uri);
}
}
else {
// if the user clicks on the subscribe check box, we handle it here
if (t.localName == "image") {
ReverseStateFromNode(t.parentNode.parentNode.parentNode);
return;
}
2000-09-07 08:17:32 +00:00
var name = t.parentNode.parentNode.getAttribute('name');
if (name && (name.length > 0)) {
gNameField.setAttribute('value',name);
}
}
}
}
2000-03-28 04:03:25 +00:00
function Refresh()
2000-03-28 04:03:25 +00:00
{
// force it to talk to the server
SetUpTree(true);
2000-03-28 04:03:25 +00:00
}
2000-05-12 06:43:11 +00:00
function trackGroupInTree()
{
var portion = gNameField.value;
selectNodeByName( portion );
}
2000-09-18 21:44:54 +00:00
2000-05-12 06:43:11 +00:00
function selectNodeByName( aMatchString )
{
var lastDot = aMatchString.lastIndexOf(gFolderDelimiter);
var nodeValue = lastDot != -1 ? aMatchString.substring(0, lastDot) : aMatchString;
var chain = aMatchString.split(gFolderDelimiter);
2000-09-18 21:44:54 +00:00
var node;
2000-05-12 06:43:11 +00:00
if( chain.length == 1 ) {
2000-09-18 21:44:54 +00:00
if (lastTreeChildrenValue != "") {
node = getTreechildren(gSubscribeTree);
if( !node ) return;
lastTreeChildrenValue = "";
lastTreeChildren = node;
//dump("cache miss!\n");
}
else {
node = lastTreeChildren;
//dump("cache hit!\n");
}
2000-05-12 06:43:11 +00:00
}
else {
2000-09-18 21:44:54 +00:00
// if we can, use the cached tree children
if (nodeValue != lastTreeChildrenValue) {
node = gSubscribeTree.getElementsByAttribute("name",nodeValue)[0];
// expand the node, if we need to
if( node.getAttribute("container") == "true" &&
node.getAttribute("open") != "true" ) {
node.setAttribute("open","true");
}
node = getTreechildren(node);
//dump("*** node = " + node.localName + "\n");
lastTreeChildren = node;
lastTreeChildrenValue = nodeValue;
//dump("cache miss!\n");
}
else {
//dump("cache hit!\n");
node = lastTreeChildren;
}
2000-05-12 06:43:11 +00:00
}
2000-09-18 21:44:54 +00:00
// find the match, using a binary search.
var totalItems = node.childNodes.length;
if (totalItems == 0) return;
var lastLow = 0;
var lastHigh = totalItems;
while (true) {
var i = Math.floor((lastHigh + lastLow) / 2);
//dump(i+","+lastLow+","+lastHigh+"\n");
var currItem = node.childNodes[i];
var currValue = (currItem.getAttribute("name")).substring(0,aMatchString.length);
//dump(currValue+" vs "+aMatchString+"\n");
if (currValue > aMatchString) {
if (lastHigh == i) return;
lastHigh = i;
}
else if (currValue < aMatchString) {
if (lastLow == i) return;
lastLow = i;
}
else {
SelectFirstMatch(lastLow, i, node.childNodes, aMatchString);
return;
2000-09-18 21:44:54 +00:00
}
}
2000-05-12 06:43:11 +00:00
}
function SelectFirstMatch(startNode, endNode, nodes, matchStr)
{
// this code is to make sure we select the alphabetically first match
// not just any match (see bug #60242)
// find the match, using a binary search.
var lastMatch = nodes[endNode];
var totalItems = endNode - startNode;
if (totalItems == 0) {
gSubscribeTree.selectItem( lastMatch );
gSubscribeTree.ensureElementIsVisible( lastMatch );
return;
}
var lastLow = startNode;
var lastHigh = endNode;
while (true) {
var i = Math.floor((lastHigh + lastLow) / 2);
//dump(i+","+lastLow+","+lastHigh+"\n");
var currItem = nodes[i];
var currValue = (currItem.getAttribute("name")).substring(0,matchStr.length);
//dump(currValue+" vs "+matchStr+"\n");
if (currValue > matchStr) {
gSubscribeTree.selectItem( lastMatch );
gSubscribeTree.ensureElementIsVisible( lastMatch );
return;
}
else if (currValue < matchStr) {
if (lastLow == i) {
gSubscribeTree.selectItem( lastMatch );
gSubscribeTree.ensureElementIsVisible( lastMatch );
return;
}
lastLow = i;
}
else {
lastMatch = currItem;
if (lastHigh == i) {
gSubscribeTree.selectItem( lastMatch );
gSubscribeTree.ensureElementIsVisible( lastMatch );
return;
}
lastHigh = i;
}
}
}
2000-05-12 06:43:11 +00:00
function getTreechildren( aTreeNode )
{
if( aTreeNode.childNodes )
{
for( var i = 0; i < aTreeNode.childNodes.length; i++ )
{
2000-06-07 01:05:50 +00:00
if( aTreeNode.childNodes[i].localName.toLowerCase() == "treechildren" )
2000-05-12 06:43:11 +00:00
return aTreeNode.childNodes[i];
}
return aTreeNode;
}
return null;
}