home *** CD-ROM | disk | FTP | other *** search
/ SVM Mac 58 / CD-ROM N°58.iso / navigateurs / Netscape Folder / chrome / sidebar / content / default / customize.js < prev    next >
Encoding:
JavaScript  |  2000-04-19  |  18.9 KB  |  569 lines  |  [TEXT/MOSS]

  1. /* -*- Mode: Java; tab-width: 4; insert-tabs-mode: nil; c-basic-offset: 2 -*-
  2.  * The contents of this file are subject to the Netscape Public
  3.  * License Version 1.1 (the "License"); you may not use this file
  4.  * except in compliance with the License. You may obtain a copy of
  5.  * the License at http://www.mozilla.org/NPL/
  6.  *  
  7.  * Software distributed under the License is distributed on an "AS
  8.  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  9.  * implied. See the License for the specific language governing
  10.  * rights and limitations under the License.
  11.  *  
  12.  * The Original Code is Mozilla Communicator client code, released
  13.  * March 31, 1998.
  14.  * 
  15.  * The Initial Developer of the Original Code is Netscape
  16.  * Communications Corporation. Portions created by Netscape are
  17.  * Copyright (C) 1998-1999 Netscape Communications Corporation. All
  18.  * Rights Reserved.
  19.  * 
  20.  */
  21.  
  22. // the rdf service
  23. var RDF = 'component://netscape/rdf/rdf-service'
  24. RDF = Components.classes[RDF].getService();
  25. RDF = RDF.QueryInterface(Components.interfaces.nsIRDFService);
  26.  
  27. var NC = "http://home.netscape.com/NC-rdf#";
  28.  
  29. var sidebarObj = new Object;
  30. var original_panels = new Array();
  31.  
  32. function debug(msg)
  33. {
  34.   //dump(msg+"\n");
  35. }
  36.  
  37. function Init()
  38. {
  39.   var all_panels_datasources = window.arguments[0];
  40.   var all_panels_resource    = window.arguments[1];
  41.   sidebarObj.datasource_uri     = window.arguments[2];
  42.   sidebarObj.resource           = window.arguments[3];
  43.  
  44.   debug("Init: all panels datasources = " + all_panels_datasources);
  45.   debug("Init: all panels resource    = " + all_panels_resource);
  46.   debug("Init: sidebarObj.datasource_uri = " + sidebarObj.datasource_uri);
  47.   debug("Init: sidebarObj.resource       = " + sidebarObj.resource);
  48.  
  49.   var all_panels   = document.getElementById('other-panels');
  50.   var current_panels = document.getElementById('current-panels');
  51.  
  52.   all_panels_datasources = all_panels_datasources.replace(/^\s+/,'');
  53.   all_panels_datasources = all_panels_datasources.replace(/\s+$/,'');
  54.   all_panels_datasources = all_panels_datasources.split(/\s+/);
  55.   for (var ii = 0; ii < all_panels_datasources.length; ii++) {
  56.     debug("Init: Adding "+all_panels_datasources[ii]);
  57.  
  58.     // This will load the datasource, if it isn't already.
  59.     var datasource = RDF.GetDataSource(all_panels_datasources[ii]);
  60.     all_panels.database.AddDataSource(datasource);
  61.     current_panels.database.AddDataSource(datasource);
  62.   }
  63.   
  64.   // Add the datasource for current list of panels. It selects panels out
  65.   // of the other datasources.
  66.   debug("Init: Adding current panels, "+sidebarObj.datasource_uri);
  67.   sidebarObj.datasource = RDF.GetDataSource(sidebarObj.datasource_uri);
  68.   current_panels.database.AddDataSource(sidebarObj.datasource);
  69.  
  70.   // Root the customize dialog at the correct place.
  71.   debug("Init: reset all panels ref, "+all_panels_resource);
  72.   all_panels.setAttribute('ref', all_panels_resource);
  73.   debug("Init: reset current panels ref, "+sidebarObj.resource);
  74.   current_panels.setAttribute('ref', sidebarObj.resource);
  75.  
  76.   save_initial_panels();
  77.   enable_buttons_for_current_panels();
  78. }
  79.  
  80. // Remember the original list of panels so that
  81. // the save button can be enabled when something changes.
  82. function save_initial_panels()
  83. {
  84.   var root = document.getElementById('current-panels-root');
  85.   for (var node = root.firstChild; node != null; node = node.nextSibling) {
  86.     original_panels[original_panels.length] = node.getAttribute('id');
  87.   }
  88. }
  89.  
  90. function get_attr(registry,service,attr_name) {
  91.   var attr = registry.GetTarget(service,
  92.                                 RDF.GetResource(NC + attr_name),
  93.                                 true);
  94.   if (attr)
  95.     attr = attr.QueryInterface(Components.interfaces.nsIRDFLiteral);
  96.   if (attr)
  97.     attr = attr.Value;
  98.   return attr;
  99. }
  100.  
  101. function SelectChangeForOtherPanels(event, target)
  102.   // Remove the selection in the "current" panels list
  103.   var current_panels = document.getElementById('current-panels');
  104.   current_panels.clearItemSelection();
  105.   enable_buttons_for_current_panels();
  106.  
  107.   if (target.getAttribute('container') == 'true') {
  108.     if (target.getAttribute('open') == 'true') {
  109.       target.removeAttribute('open');
  110.     } else {
  111.       target.setAttribute('open','true');
  112.     }
  113.   } else {
  114.     link = target.getAttribute('link');
  115.     if (link && link != '') {
  116.       debug("Has remote datasource: "+link);
  117.       add_datasource_to_other_panels(link);
  118.       target.setAttribute('container', 'true');
  119.       target.setAttribute('open', 'true');
  120.     }
  121.   }
  122.   enable_buttons_for_other_panels();
  123. }
  124.  
  125. function add_datasource_to_other_panels(link) {
  126.   // Convert the |link| attribute into a URL
  127.   var url = document.location;
  128.   debug("Current URL:  " +url);
  129.   debug("Current link: " +link);
  130.  
  131.   uri = Components.classes['component://netscape/network/standard-url'].createInstance();
  132.   uri = uri.QueryInterface(Components.interfaces.nsIURI);
  133.   uri.spec = url;
  134.   uri = uri.resolve(link);
  135.  
  136.   debug("New URL:      " +uri);
  137.   
  138.   // Add the datasource to the tree
  139.   var all_panels = document.getElementById('other-panels');
  140.   all_panels.database.AddDataSource(RDF.GetDataSource(uri));
  141.  
  142.   // XXX This is a hack to force re-display
  143.   all_panels.setAttribute('ref', 'urn:blah:main-root');
  144. }
  145.  
  146. // Handle a selection change in the current panels.
  147. function SelectChangeForCurrentPanels() {
  148.   // Remove the selection in the available panels list
  149.   var all_panels = document.getElementById('other-panels');
  150.   all_panels.clearItemSelection();
  151.  
  152.   enable_buttons_for_current_panels();
  153.   enable_buttons_for_other_panels();
  154. }
  155.  
  156. // Move the selected item up the the current panels list.
  157. function MoveUp() {
  158.   var tree = document.getElementById('current-panels'); 
  159.   if (tree.selectedItems.length == 1) {
  160.     var selected = tree.selectedItems[0];
  161.     var before = selected.previousSibling
  162.     if (before) {
  163.       before.parentNode.insertBefore(selected, before);
  164.       tree.selectItem(selected);
  165.       tree.ensureElementIsVisible(selected);
  166.     }
  167.   }
  168.   enable_buttons_for_current_panels();
  169.   enable_save();
  170. }
  171.    
  172. // Move the selected item down the the current panels list.
  173. function MoveDown() {
  174.   var tree = document.getElementById('current-panels');
  175.   if (tree.selectedItems.length == 1) {
  176.     var selected = tree.selectedItems[0];
  177.     if (selected.nextSibling) {
  178.       if (selected.nextSibling.nextSibling) {
  179.         selected.parentNode.insertBefore(selected, selected.nextSibling.nextSibling);
  180.       }
  181.       else {
  182.         selected.parentNode.appendChild(selected);
  183.       }
  184.       tree.selectItem(selected);
  185.     }
  186.   }
  187.   enable_buttons_for_current_panels();
  188.   enable_save();
  189. }
  190.  
  191. function PreviewPanel() 
  192. {
  193.   var tree = document.getElementById('other-panels');
  194.   var database = tree.database;
  195.   var select_list = tree.selectedItems
  196.   for (var nodeIndex=0; nodeIndex<select_list.length; nodeIndex++) {
  197.     var node = select_list[nodeIndex];
  198.     if (!node)    break;
  199.     // Skip folders
  200.     if (node.getAttribute('container') == 'true') {
  201.       continue;
  202.     }
  203.     var id = node.getAttribute("id");
  204.     if (!id)      break;
  205.     var rdfNode = RDF.GetResource(id);
  206.     if (!rdfNode) break;
  207.  
  208.     var preview_name = get_attr(database, rdfNode, 'title');
  209.     var preview_URL  = get_attr(database, rdfNode, 'content');
  210.     if (!preview_URL || !preview_name) break;
  211.  
  212.     var preview = window.open("chrome://sidebar/content/preview.xul",
  213.                               "_blank", "chrome,resizable");
  214.     preview.panel_name = preview_name;
  215.     preview.panel_URL = preview_URL;
  216.   }
  217. }
  218.  
  219. // Add the selected panel(s).
  220. function AddPanel() 
  221. {
  222.   var tree = document.getElementById('other-panels');
  223.   var database = tree.database;
  224.   var select_list = tree.selectedItems
  225.   for (var nodeIndex=0; nodeIndex<select_list.length; nodeIndex++) {
  226.     var node = select_list[nodeIndex];
  227.     if (!node)    break;
  228.     // Skip folders.
  229.     if (node.getAttribute('container') == 'true') {
  230.       continue;
  231.     }
  232.     var id = node.getAttribute("id");
  233.     // No id? Sorry. Only nodes with id's can get
  234.     // in the current panel list.
  235.     if (!id)      break;
  236.     var rdfNode = RDF.GetResource(id);
  237.     // You need an rdf node too. Sorry, those are the rules.
  238.     if (!rdfNode) break;
  239.  
  240.     // Add the panel to the current list.
  241.     add_node_to_current_list(database, rdfNode);
  242.   }
  243.  
  244.   // Remove the selection in the other list.
  245.   // Selection will move to "current" list.
  246.   var all_panels = document.getElementById('other-panels');
  247.   all_panels.clearItemSelection();
  248.  
  249.   enable_buttons_for_current_panels();
  250.   enable_buttons_for_other_panels();
  251.   enable_save();
  252. }
  253.  
  254. // Copy a panel node into a database such as the current panel list.
  255. function add_node_to_current_list(registry, service)
  256. {
  257.   debug("Adding "+service.Value);
  258.  
  259.   // Copy out the attributes we want
  260.   var option_title     = get_attr(registry, service, 'title');
  261.   var option_customize = get_attr(registry, service, 'customize');
  262.   var option_content   = get_attr(registry, service, 'content');
  263.  
  264.   var tree     = document.getElementById('current-panels'); 
  265.   var treeroot = document.getElementById('current-panels-root'); 
  266.  
  267.   // Check to see if the panel already exists...
  268.   for (var ii = treeroot.firstChild; ii != null; ii = ii.nextSibling) {
  269.     if (ii.getAttribute('id') == service.Value) {
  270.       // The panel is already in the current panel list.
  271.       // Avoid adding it twice.
  272.       tree.selectItem(ii);
  273.       tree.ensureElementIsVisible(ii);
  274.       return;
  275.     }
  276.   }
  277.  
  278.   // Create a treerow for the new panel
  279.   var item = document.createElement('treeitem');
  280.   var row  = document.createElement('treerow');
  281.   var cell = document.createElement('treecell');
  282.   
  283.   // Copy over the attributes
  284.   item.setAttribute('id', service.Value);
  285.   item.setAttribute('customize', option_customize);
  286.   item.setAttribute('content', option_content);
  287.   cell.setAttribute('value', option_title);
  288.  
  289.   // Add it to the current panels tree
  290.   item.appendChild(row);
  291.   row.appendChild(cell);
  292.   treeroot.appendChild(item);
  293.  
  294.   // Select is only if the caller wants to.
  295.   tree.selectItem(item);
  296.   tree.ensureElementIsVisible(item);
  297. }
  298.  
  299. // Remove the selected panel(s) from the current list tree.
  300. function RemovePanel()
  301. {
  302.   var tree = document.getElementById('current-panels');
  303.  
  304.   var nextNode = null;
  305.   var numSelected = tree.selectedItems.length
  306.   while (tree.selectedItems.length > 0) {
  307.     var selectedNode = tree.selectedItems[0]
  308.     nextNode = selectedNode.nextSibling;
  309.     if (!nextNode) {
  310.       nextNode = selectedNode.previousSibling;
  311.     }
  312.     selectedNode.parentNode.removeChild(selectedNode)
  313.   } 
  314.   
  315.   if (nextNode) {
  316.     tree.selectItem(nextNode)
  317.   }
  318.   enable_buttons_for_current_panels();
  319.   enable_save();
  320. }
  321.  
  322. // Bring up a new window with the customize url 
  323. // for an individual panel.
  324. function CustomizePanel() 
  325. {
  326.   var tree  = document.getElementById('current-panels');
  327.   var numSelected = tree.selectedItems.length;
  328.  
  329.   if (numSelected == 1) {
  330.     var selectedNode  = tree.selectedItems[0];
  331.     var customize_url = selectedNode.getAttribute('customize');
  332.  
  333.     debug("url   = " + customize_url);
  334.  
  335.     if (!customize_url) return;
  336.  
  337.     window.open(customize_url, "_blank", "resizable,width=690,height=600");
  338.   }
  339.   enable_save();
  340. }
  341.  
  342. // Serialize the new list of panels.
  343. function Save()
  344. {
  345.   var all_panels = document.getElementById('other-panels');
  346.   var current_panels = document.getElementById('current-panels');
  347.  
  348.   // Iterate through the 'current-panels' tree to collect the panels
  349.   // that the user has chosen. We need to do this _before_ we remove
  350.   // the panels from the datasource, because the act of removing them
  351.   // from the datasource will change the tree!
  352.   var panels = new Array();
  353.   var root = document.getElementById('current-panels-root');
  354.   for (var node = root.firstChild; node != null; node = node.nextSibling) {
  355.     panels[panels.length] = node.getAttribute('id');
  356.   }
  357.  
  358.   // Cut off the connection between the dialog and the datasource.
  359.   // The dialog is closed at the end of this function.
  360.   // Without this, the dialog tries to update as it is being destroyed.
  361.   current_panels.setAttribute('ref', 'rdf:null');
  362.  
  363.   start_batch(sidebarObj.datasource, sidebarObj.resource);
  364.  
  365.   // Create a "container" wrapper around the current panels to
  366.   // manipulate the RDF:Seq more easily.
  367.   var container = Components.classes["component://netscape/rdf/container"].createInstance();
  368.   container = container.QueryInterface(Components.interfaces.nsIRDFContainer);
  369.   container.Init(sidebarObj.datasource, RDF.GetResource(sidebarObj.resource));
  370.  
  371.   // Remove all the current panels from the datasource.
  372.   var current_panels = container.GetElements();
  373.   while (current_panels.HasMoreElements()) {
  374.     panel = current_panels.GetNext();
  375.     id = panel.QueryInterface(Components.interfaces.nsIRDFResource).Value;
  376.  
  377.     // If this panel is not in the new list,
  378.     // or, if description of this panel is in the all panels list,
  379.     // then, remove all assertions for the panel to avoid leaving
  380.     // unneeded assertions behind and to avoid multiply asserted
  381.     // attributes, respectively.
  382.     if (!has_element(panels, id) || 
  383.         has_targets(all_panels.database, panel)) {
  384.       delete_resource_deeply(container, panel);
  385.     } else {
  386.       container.RemoveElement(panel, false);
  387.     }
  388.   }
  389.  
  390.   // Add the new list of panels
  391.   for (var ii = 0; ii < panels.length; ++ii) {
  392.     copy_resource_deeply(all_panels.database, RDF.GetResource(panels[ii]),
  393.                          container);
  394.   }
  395.  
  396.   end_batch(sidebarObj.datasource, sidebarObj.resource);
  397.  
  398.   // Write the modified panels out.
  399.   sidebarObj.datasource.QueryInterface(Components.interfaces.nsIRDFRemoteDataSource).Flush();
  400.  
  401.   window.close();
  402. }
  403.  
  404. // Search for an element in an array
  405. function has_element(array, element) {
  406.   for (var ii=0; ii < array.length; ii++) {
  407.     if (array[ii] == element) {
  408.       return true;
  409.     }
  410.   }
  411.   return false;
  412. }
  413.  
  414. // Search for targets from resource in datasource
  415. function has_targets(datasource, resource) {
  416.   var arcs = datasource.ArcLabelsOut(resource);
  417.   return arcs.HasMoreElements();
  418. }
  419.  
  420. // Mark the beginning of a batch by asserting inbatch="true"
  421. // into the datasource. The observer in sidebarOverlay.js uses 
  422. // this to remember the panel selection.
  423. function start_batch(datasource, resource) {
  424.   datasource.Assert(RDF.GetResource(resource),
  425.                     RDF.GetResource(NC + "inbatch"),
  426.                     RDF.GetLiteral("true"),
  427.                     true);
  428. }
  429.  
  430. // Mark the end of a batch by unasserting 'inbatch' on the datasource.
  431. function end_batch(datasource, resource) {
  432.   datasource.Unassert(RDF.GetResource(resource),
  433.                       RDF.GetResource(NC + "inbatch"),
  434.                       RDF.GetLiteral("true"));
  435. }
  436.  
  437. // Remove a resource and all the arcs out from it.
  438. function delete_resource_deeply(container, resource) {
  439.   var arcs = container.DataSource.ArcLabelsOut(resource);
  440.   while (arcs.HasMoreElements()) {
  441.     var arc = arcs.GetNext();
  442.     var targets = container.DataSource.GetTargets(resource, arc, true);
  443.     while (targets.HasMoreElements()) {
  444.       var target = targets.GetNext();
  445.       container.DataSource.Unassert(resource, arc, target, true);
  446.     }
  447.   }
  448.   container.RemoveElement(panel, false);
  449. }
  450.  
  451. // Copy a resource and all its arcs out to a new container.
  452. function copy_resource_deeply(source_datasource, resource, dest_container) {
  453.   var arcs = source_datasource.ArcLabelsOut(resource);
  454.   while (arcs.HasMoreElements()) {
  455.     var arc = arcs.GetNext();
  456.     var targets = source_datasource.GetTargets(resource, arc, true);
  457.     while (targets.HasMoreElements()) {
  458.       var target = targets.GetNext();
  459.       dest_container.DataSource.Assert(resource, arc, target, true);
  460.     }
  461.   }
  462.   dest_container.AppendElement(resource);
  463. }
  464.  
  465. function enable_buttons_for_other_panels()
  466. {
  467.   var add_button = document.getElementById('add_button');
  468.   var preview_button = document.getElementById('preview_button');
  469.   var all_panels = document.getElementById('other-panels');
  470.  
  471.   var num_selected = 0;
  472.   // Only count non-folders as selected for button enabling
  473.   for (var ii=0; ii<all_panels.selectedItems.length; ii++) {
  474.     var node = all_panels.selectedItems[ii];
  475.     if (node.getAttribute('container') != 'true') {
  476.       num_selected++;
  477.     }
  478.   }
  479.   if (num_selected > 0) {
  480.     add_button.removeAttribute('disabled');
  481.     preview_button.removeAttribute('disabled');
  482.   }
  483.   else {
  484.     add_button.setAttribute('disabled','true');
  485.     preview_button.setAttribute('disabled','true');
  486.   }
  487. }
  488.  
  489. function enable_buttons_for_current_panels() {
  490.   var up        = document.getElementById('up');
  491.   var down      = document.getElementById('down');
  492.   var tree      = document.getElementById('current-panels');
  493.   var customize = document.getElementById('customize-button');
  494.   var remove    = document.getElementById('remove-button');
  495.  
  496.   var numSelected = tree.selectedItems.length;
  497.  
  498.   var noneSelected, isFirst, isLast, selectedNode
  499.  
  500.   if (numSelected > 0) {
  501.     selectedNode = tree.selectedItems[0]
  502.     isFirst = selectedNode == selectedNode.parentNode.firstChild
  503.     isLast  = selectedNode == selectedNode.parentNode.lastChild
  504.   }
  505.  
  506.   // up /\ button
  507.   if (numSelected != 1 || isFirst) {
  508.     up.setAttribute('disabled', 'true');
  509.   } else {
  510.     up.removeAttribute('disabled');
  511.   }
  512.   // down \/ button
  513.   if (numSelected != 1 || isLast) {
  514.     down.setAttribute('disabled', 'true');
  515.   } else {
  516.     down.removeAttribute('disabled');
  517.   }
  518.   // "Customize..." button
  519.   var customizeURL = null;
  520.   if (numSelected == 1) {
  521.     customizeURL = selectedNode.getAttribute('customize');
  522.   }
  523.   if (customizeURL == null || customizeURL == '') {
  524.     customize.setAttribute('disabled','true');
  525.   } else {
  526.     customize.removeAttribute('disabled');
  527.   }
  528.   // "Remove" button
  529.   if (numSelected == 0) {
  530.     remove.setAttribute('disabled','true');
  531.   } else {
  532.     remove.removeAttribute('disabled');
  533.   }
  534. }
  535.  
  536. // Check to see if the "current" panel list has changed.
  537. // If so, enable the save button.
  538. function enable_save() {
  539.   var root = document.getElementById('current-panels-root');
  540.   var panels = root.childNodes;  
  541.   var list_unchanged = (panels.length == original_panels.length);
  542.  
  543.   for (var ii = 0; ii < panels.length && list_unchanged; ii++) {
  544.     if (original_panels[ii] != panels.item(ii).getAttribute('id')) {
  545.       list_unchanged = false;
  546.     }
  547.   }
  548.   var save_button = document.getElementById('save_button');
  549.   if (list_unchanged) {
  550.     save_button.setAttribute('disabled','true');  
  551.   } else {
  552.     save_button.removeAttribute('disabled');
  553.   }
  554. }
  555.  
  556. function dump_attributes(node) {
  557.   var attributes = node.attributes
  558.  
  559.   if (!attributes || attributes.length == 0) {
  560.     debug("no attributes\n")
  561.   }
  562.   for (var ii=0; ii < attributes.length; ii++) {
  563.     var attr = attributes.item(ii)
  564.     debug("attr "+ii+": "+ attr.name +"="+attr.value)
  565.   }
  566. }
  567.  
  568.