home *** CD-ROM | disk | FTP | other *** search
/ Chip 2002 January / 01_02.iso / software / netscape62win / mail.xpi / bin / chrome / messenger.jar / content / messenger / subscribe.js < prev    next >
Text File  |  2001-07-17  |  14KB  |  505 lines

  1. var gSubscribeTree = null;
  2. var okCallback = null;
  3. var gChangeTable = {};
  4. var gServerURI = null;
  5. var gSubscribableServer = null;
  6. var gStatusBar = null;
  7. var gNameField = null;
  8. var gNameFieldLabel = null;
  9. var gFolderDelimiter = ".";
  10. var gStatusFeedback = new nsMsgStatusFeedback;
  11. var gSubscribeDeck = null;
  12. var gSearchView = null;
  13. var gSearchOutlinerBoxObject = null;
  14. // the rdf service
  15. var RDF = '@mozilla.org/rdf/rdf-service;1'
  16. RDF = Components.classes[RDF].getService();
  17. RDF = RDF.QueryInterface(Components.interfaces.nsIRDFService);
  18. var subscribeDS = RDF.GetDataSource("rdf:subscribe");
  19.  
  20. // get the "subscribed" atom
  21. var atomService = Components.classes["@mozilla.org/atom-service;1"].getService().QueryInterface(Components.interfaces.nsIAtomService);
  22. var gSubscribedAtom = atomService.getAtom("subscribed").QueryInterface(Components.interfaces.nsISupports);
  23.  
  24. var gSubscribeBundle;
  25.  
  26. function goDoCommand()
  27. {
  28. }
  29.  
  30. function Stop()
  31. {
  32.     //dump("Stop()\n")
  33.     if (gSubscribableServer) {
  34.         gSubscribableServer.stopPopulating(msgWindow);
  35.     }
  36. }
  37.  
  38. function SetServerTypeSpecificTextValues()
  39. {
  40.     if (!gServerURI) return;
  41.  
  42.     var serverType = GetMsgFolderFromUri(gServerURI).server.type;
  43.     
  44.     // set the server specific ui elements
  45.     var stringName = "foldersheaderfor-" + serverType;
  46.     var stringval = gSubscribeBundle.getString(stringName);
  47.     var element = document.getElementById("foldersheaderlabel");
  48.     element.setAttribute('label',stringval);
  49.     element = document.getElementById("nameCol");
  50.     element.setAttribute('label',stringval);
  51.  
  52.     //set the delimiter
  53.     try {
  54.         gFolderDelimiter = gSubscribableServer.delimiter;
  55.     }
  56.     catch (ex) {
  57.         //dump(ex + "\n");
  58.         gFolderDelimiter = ".";
  59.     }
  60. }
  61.  
  62. function onServerClick(event)
  63. {
  64.     var item = event.target;
  65.     gServerURI = item.id;
  66.     //dump("gServerURI="+gServerURI+"\n");
  67.  
  68.     SetUpTree(false);
  69.  
  70.     SetServerTypeSpecificTextValues();
  71. }
  72.  
  73. function SetUpServerMenu()
  74. {
  75.     //dump("SetUpServerMenu()\n");
  76.  
  77.     var serverMenu = document.getElementById("serverMenu");
  78.     var menuitems = serverMenu.getElementsByAttribute("id", gServerURI);
  79.  
  80.     try {
  81.         //dump("gServerURI="+gServerURI+"\n");
  82.         //dump("menuitems="+menuitems+"\n");
  83.         //dump("menuitems[0]="+menuitems[0]+"\n");
  84.         //dump("serverMenu="+serverMenu+"\n");
  85.         serverMenu.selectedItem = menuitems[0];
  86.     }
  87.     catch (ex) {
  88.         //dump("failed to set the selected server: " + ex + "\n");
  89.     }
  90.  
  91.     SetServerTypeSpecificTextValues();
  92. }
  93.  
  94. var MySubscribeListener = {
  95.     OnDonePopulating: function() {
  96.         gStatusFeedback.showProgress(100);
  97.         gStatusFeedback.showStatusString(gSubscribeBundle.getString("doneString"));
  98.         gStatusBar.setAttribute("mode","normal");
  99.  
  100.         // only re-root the tree, if it is null.
  101.         // otherwise, we are in here because we are populating
  102.         // a part of the tree
  103.   
  104.         var refValue = gSubscribeTree.getAttribute('ref');
  105.         //dump("ref = " + refValue + refValue.length + "\n");
  106.         if (refValue == "null") {
  107.             //dump("root subscribe tree at: "+ gServerURI +"\n");
  108.             gSubscribeTree.database.AddDataSource(subscribeDS);
  109.             gSubscribeTree.setAttribute('ref',gServerURI);
  110.         }
  111.     }
  112. };
  113.  
  114. function SetUpTree(forceToServer)
  115. {
  116.     //dump("SetUpTree()\n");
  117.     
  118.     gStatusBar = document.getElementById('statusbar-icon');
  119.     if (!gServerURI) return;
  120.  
  121.     var folder = GetMsgFolderFromUri(gServerURI);
  122.     var server = folder.server;
  123.  
  124.     try {
  125.           CleanUpSearchView();
  126.           gSubscribableServer = server.QueryInterface(Components.interfaces.nsISubscribableServer);
  127.           gSubscribeTree.setAttribute('ref',null);
  128.  
  129.           // enable (or disable) the search related UI
  130.           EnableSearchUI();
  131.  
  132.           // clear out the text field when switching server
  133.           gNameField.setAttribute('value',"");
  134.  
  135.           // since there is no text, switch to the non-search view...
  136.           SwitchToNormalView();
  137.  
  138.           gSubscribeTree.database.RemoveDataSource(subscribeDS);
  139.           gSubscribableServer.subscribeListener = MySubscribeListener;
  140.  
  141.           gStatusFeedback.showProgress(0);
  142.           gStatusFeedback.showStatusString(gSubscribeBundle.getString("pleaseWaitString"));
  143.           gStatusBar.setAttribute("mode","undetermined");
  144.  
  145.           gSubscribableServer.startPopulating(msgWindow, forceToServer);
  146.     }
  147.     catch (ex) {
  148.           //dump("failed to populate subscribe ds: " + ex + "\n");
  149.     }
  150. }
  151.  
  152.  
  153. function SubscribeOnUnload()
  154. {
  155.   try {
  156.     CleanUpSearchView();
  157.     gSubscribeTree.database.RemoveDataSource(subscribeDS);
  158.   }
  159.   catch (ex) {
  160.     dump("failed to remove the subscribe ds: " + ex + "\n");
  161.   }
  162. }
  163.  
  164. function EnableSearchUI()
  165. {
  166.   if (gSubscribableServer.supportsSubscribeSearch) {
  167.     gNameField.removeAttribute('disabled');
  168.     gNameFieldLabel.removeAttribute('disabled');
  169.   }
  170.   else {
  171.     gNameField.setAttribute('disabled',true);
  172.     gNameFieldLabel.setAttribute('disabled',true);
  173.   }
  174. }
  175.  
  176. function SubscribeOnLoad()
  177. {
  178.   //dump("SubscribeOnLoad()\n");
  179.   gSubscribeBundle = document.getElementById("bundle_subscribe");
  180.     
  181.   gSubscribeTree = document.getElementById('subscribetree');
  182.   gSearchOutlinerBoxObject = document.getElementById("searchOutliner").boxObject.QueryInterface(Components.interfaces.nsIOutlinerBoxObject);
  183.   gNameField = document.getElementById('namefield');
  184.   gNameFieldLabel = document.getElementById('namefieldlabel');
  185.   gSubscribeDeck = document.getElementById("subscribedeck");
  186.  
  187.   msgWindow = Components.classes[msgWindowContractID].createInstance(Components.interfaces.nsIMsgWindow);
  188.   msgWindow.statusFeedback = gStatusFeedback;
  189.   msgWindow.SetDOMWindow(window);
  190.  
  191.   doSetOKCancel(subscribeOK,subscribeCancel);
  192.  
  193.     // look in arguments[0] for parameters
  194.     if (window.arguments && window.arguments[0]) {
  195.         if ( window.arguments[0].okCallback ) {
  196.             top.okCallback = window.arguments[0].okCallback;
  197.         }
  198.     }
  199.     
  200.     gServerURI = null;
  201.     if (window.arguments[0].preselectedURI) {
  202.         var uri = window.arguments[0].preselectedURI;
  203.         //dump("subscribe: got a uri," + uri + "\n");
  204.         var folder = GetMsgFolderFromUri(uri);
  205.         //dump("folder="+folder+"\n");
  206.         //dump("folder.server="+folder.server+"\n");
  207.         try {
  208.                         CleanUpSearchView();
  209.             gSubscribableServer = folder.server.QueryInterface(Components.interfaces.nsISubscribableServer);
  210.                         // enable (or disable) the search related UI
  211.                         EnableSearchUI();
  212.             gServerURI = folder.server.serverURI;
  213.         }
  214.         catch (ex) {
  215.             //dump("not a subscribable server\n");
  216.                         CleanUpSearchView();
  217.             gSubscribableServer = null;
  218.             gServerURI = null;
  219.         }
  220.     }
  221.  
  222.     if (!gServerURI) {
  223.         //dump("subscribe: no uri\n");
  224.         //dump("xxx todo:  use the default news server.  right now, I'm just using the first server\n");
  225.         var serverMenu = document.getElementById("serverMenu");
  226.         var menuitems = serverMenu.getElementsByTagName("menuitem");
  227.         
  228.         if (menuitems.length > 1) {
  229.             gServerURI = menuitems[1].id;
  230.         }
  231.         else {
  232.             //dump("xxx todo none of your servers are subscribable\n");
  233.             //dump("xxx todo fix this by disabling subscribe if no subscribable server or, add a CREATE SERVER button, like in 4.x\n");
  234.             return;
  235.         }
  236.     }
  237.  
  238.     SetUpServerMenu();
  239.  
  240.     SetUpTree(false);
  241.  
  242.     gNameField.focus();
  243. }
  244.  
  245. function subscribeOK()
  246. {
  247.     //dump("in subscribeOK()\n")
  248.     if (top.okCallback) {
  249.         top.okCallback(top.gChangeTable);
  250.     }
  251.     Stop();
  252.     if (gSubscribableServer) {
  253.         gSubscribableServer.subscribeCleanup();
  254.     }
  255.     return true;
  256. }
  257.  
  258. function subscribeCancel()
  259. {
  260.   Stop();
  261.   if (gSubscribableServer) {
  262.     gSubscribableServer.subscribeCleanup();
  263.   }
  264.   return true;
  265. }
  266.  
  267. function SetState(name,state)
  268. {
  269.   var changed = gSubscribableServer.setState(name, state);
  270.   if (changed) {
  271.     StateChanged(name,state);
  272.   }
  273. }
  274.  
  275. function changeTableRecord(server, name, state) 
  276. {
  277.   this.server = server;
  278.   this.name = name;
  279.   this.state = state;
  280. }
  281.  
  282. function StateChanged(name,state)
  283. {
  284.   if (gServerURI in gChangeTable) {
  285.     if (name in gChangeTable[gServerURI]) {
  286.       var oldValue = gChangeTable[gServerURI][name];
  287.       if (oldValue != state)
  288.         delete gChangeTable[gServerURI][name];
  289.     }
  290.     else {
  291.       gChangeTable[gServerURI][name] = state;
  292.     }
  293.   }
  294.   else {
  295.     gChangeTable[gServerURI] = {};
  296.     gChangeTable[gServerURI][name] = state;
  297.   }
  298. }
  299.  
  300. function InSearchMode()
  301. {
  302.     // search is the second card in the deck
  303.     return (gSubscribeDeck.getAttribute("index") == "1");
  304. }
  305.  
  306. function SearchOnClick(event)
  307. {
  308.   // we only care about button 0 (left click) events
  309.   if (event.button != 0) return;
  310.  
  311.   var t = event.originalTarget;
  312.  
  313.   if (t.localName == "outlinerbody") {
  314.     var row = new Object;
  315.     var colID = new Object;
  316.     var childElt = new Object;
  317.  
  318.     gSearchOutlinerBoxObject.getCellAt(event.clientX, event.clientY, row, colID, childElt);
  319.  
  320.     // if they are clicking on empty rows, drop the event 
  321.     if (row.value + 1 > gSearchView.rowCount) return;
  322.  
  323.     if (colID.value == "subscribedCol") {
  324.       if (event.detail != 2) {
  325.         // single clicked on the check box 
  326.         // (in the "subscribedCol" column) reverse state
  327.         // if double click, do nothing
  328.         ReverseStateFromRow(row.value);
  329.       }
  330.     }
  331.     else if (event.detail == 2) {
  332.       // double clicked on a row, reverse state
  333.       ReverseStateFromRow(row.value);
  334.     }
  335.  
  336.     // invalidate the row
  337.     InvalidateSearchOutlinerRow(row.value);
  338.   }
  339. }
  340.  
  341. function ReverseStateFromRow(row)
  342. {
  343.     // to determine if the row is subscribed or not,
  344.     // we get the properties for the "subscribedCol" cell in the row
  345.     // and look for the "subscribed" property
  346.     // if the "subscribed" atom is in the list of properties
  347.     // we are subscribed
  348.     var properties = Components.classes["@mozilla.org/supports-array;1"].createInstance(Components.interfaces.nsISupportsArray);
  349.     gSearchView.getCellProperties(row, "subscribedCol", properties);
  350.  
  351.     var isSubscribed = (properties.GetIndexOf(gSubscribedAtom) != -1);
  352.    
  353.     var name = gSearchView.getCellText(row,"nameCol");
  354.     // we need to escape the name because
  355.     // some news servers have newsgroups with non ASCII names
  356.     // we need to escape those name before calling SetState()
  357.     SetState(escape(name), !isSubscribed);
  358. }
  359.  
  360. function SetSubscribeState(state)
  361. {
  362.   try {
  363.     if (InSearchMode()) {
  364.         // if we are in "search" mode, we need to iterate over the
  365.         // outliner selection, and set the state for all elements
  366.         // in the selection
  367.         var outlinerSelection = gSearchView.selection; 
  368.         for (var i=0;i<outlinerSelection.getRangeCount();i++) {
  369.           var start = new Object;
  370.           var end = new Object;
  371.           outlinerSelection.getRangeAt(i,start,end);
  372.           for (var k=start.value;k<=end.value;k++) {
  373.             var name = gSearchView.getCellText(k,"nameCol");
  374.             // we need to escape the name because
  375.             // some news servers have newsgroups with non ASCII names
  376.             // we need to escape those name before calling SetState()
  377.             SetState(escape(name),state);
  378.           }
  379.         }
  380.         // force a repaint of the outliner since states have changed
  381.         InvalidateSearchOutliner();
  382.     }
  383.     else {
  384.       // we are in the "normal" mode
  385.       var groupList = gSubscribeTree.selectedItems;
  386.       for (var i=0;i<groupList.length;i++) {
  387.         var group = groupList[i];
  388.         var name = group.getAttribute('name');
  389.         SetState(name,state);
  390.       }
  391.     }
  392.   }
  393.   catch (ex) {
  394.     //dump("SetSubscribedState failed:  " + ex + "\n");
  395.   }
  396. }
  397.  
  398. function ReverseStateFromNode(node)
  399. {
  400.   var state;
  401.  
  402.   if (node.getAttribute('Subscribed') == "true") {
  403.     state = false;
  404.   }
  405.   else {
  406.     state = true;
  407.   }
  408.  
  409.   var uri = node.getAttribute('id');
  410.   var name = node.getAttribute('name');
  411.   SetState(name, state);
  412. }
  413.  
  414.  
  415. function SubscribeOnClick(event)
  416. {
  417.   // we only care about button 0 (left click) events
  418.   if (event.button != 0) return;
  419.  
  420.   var t = event.originalTarget;
  421.  
  422.     if (event.detail == 2) {
  423.         ReverseStateFromNode(t.parentNode.parentNode);
  424.     }
  425.     else {
  426.          if (t.getAttribute('twisty') == 'true') {
  427.             var treeitem = t.parentNode.parentNode.parentNode;
  428.             var open = treeitem.getAttribute('open');
  429.             if(open == "true") {
  430.                 var uri = treeitem.getAttribute("id");    
  431.                 
  432.                 //dump("do twisty for " + uri + "\n");
  433.  
  434.                 gStatusFeedback.showProgress(0);
  435.                 gStatusFeedback.showStatusString(gSubscribeBundle.getString("pleaseWaitString"));
  436.                 gStatusBar.setAttribute("mode","undetermined");
  437.  
  438.                 gSubscribableServer.startPopulatingWithUri(msgWindow, true /* force to server */, uri);
  439.             }
  440.         }
  441.         else {
  442.             // if the user clicks on the subscribe check box, we handle it here
  443.             if (t.localName == "image") {
  444.                 ReverseStateFromNode(t.parentNode.parentNode.parentNode);
  445.                 return;
  446.             }
  447.  
  448.         }
  449.     }
  450. }
  451.  
  452. function Refresh()
  453. {
  454.     // force it to talk to the server
  455.     SetUpTree(true);
  456. }
  457.  
  458. function InvalidateSearchOutlinerRow(row)
  459. {
  460.     gSearchOutlinerBoxObject.invalidateRow(row);
  461. }
  462.  
  463. function InvalidateSearchOutliner()
  464. {
  465.     gSearchOutlinerBoxObject.invalidate();
  466. }
  467.  
  468. function SwitchToNormalView()
  469. {
  470.   // the first card in the deck is the "normal" view
  471.   gSubscribeDeck.setAttribute("index","0");
  472. }
  473.  
  474. function SwitchToSearchView()
  475. {
  476.   // the second card in the deck is the "search" view
  477.   gSubscribeDeck.setAttribute("index","1");
  478. }
  479.  
  480. function Search()
  481. {
  482.   var searchValue = gNameField.value;
  483.   if (searchValue.length && gSubscribableServer.supportsSubscribeSearch) {
  484.     SwitchToSearchView();
  485.     gSubscribableServer.setSearchValue(searchValue);
  486.  
  487.     if (!gSearchView && gSubscribableServer) {
  488.     gSearchView = gSubscribableServer.QueryInterface(Components.interfaces.nsIOutlinerView);
  489.       gSearchView.selection = null;
  490.     gSearchOutlinerBoxObject.view = gSearchView;
  491.   }
  492.   }
  493.   else {
  494.     SwitchToNormalView();
  495.   }
  496. }
  497.  
  498. function CleanUpSearchView()
  499. {
  500.   if (gSearchView) {
  501.     gSearchView.selection = null;
  502.     gSearchView = null;
  503.   }
  504. }
  505.