/* -*- Mode: Java; tab-width: 4; insert-tabs-mode: nil; c-basic-offset: 2 -*- * * 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 Communicator client code, released * March 31, 1998. * * The Initial Developer of the Original Code is Netscape * Communications Corporation. Portions created by Netscape are * Copyright (C) 1998-1999 Netscape Communications Corporation. All * Rights Reserved. */ // the rdf service var rdf_uri = 'component://netscape/rdf/rdf-service' var RDF = Components.classes[rdf_uri].getService() RDF = RDF.QueryInterface(Components.interfaces.nsIRDFService) var NC = "http://home.netscape.com/NC-rdf#"; // the magic number to find panels.rdf var PANELS_RDF_FILE = 66626; var SIDEBAR_VERSION = "0.0"; // the default sidebar: var sidebarObj = new Object; sidebarObj.never_built = true; function debug(msg) { // uncomment for noise //dump(msg+"\n"); } var panel_observer = new Object; panel_observer = { OnAssert : function(src,prop,target) { debug ("*** assert");}, OnUnassert : function(src,prop,target) { // Wait for unassert that marks the end of the customize changes. // See customize.js for where this is unasserted. if (prop == RDF.GetResource(NC + "inbatch")) { sidebar_open_default_panel(100, 0); } }, OnChange : function(src,prop,old_target,new_target) {}, OnMove : function(old_src,new_src,prop,target) {} } function get_sidebar_datasource_uri(panels_file_id) { try { var locator_interface = Components.interfaces.nsIFileLocator; var locator_prog_id = 'component://netscape/filelocator'; var locator_service = Components.classes[locator_prog_id].getService(); // use the fileLocator to look in the profile directory // to find 'panels.rdf', which is the // database of the user's currently selected panels. locator_service = locator_service.QueryInterface(locator_interface); // if /panels.rdf doesn't exist, GetFileLocation() will copy // bin/defaults/profile/panels.rdf to /panels.rdf var sidebar_file = locator_service.GetFileLocation(panels_file_id); if (!sidebar_file.exists()) { // this should not happen, as GetFileLocation() should copy // defaults/panels.rdf to the users profile directory return null; } debug("sidebar uri is " + sidebar_file.URLString); return sidebar_file.URLString; } catch (ex) { // this should not happen debug("Error: Unable to load panels file.\n"); return null; } } function sidebar_overlay_init() { sidebarObj.datasource_uri = get_sidebar_datasource_uri(PANELS_RDF_FILE); sidebarObj.resource = 'urn:sidebar:current-panel-list'; sidebarObj.master_datasources = get_remote_datasource_url(); sidebarObj.master_resource = 'urn:sidebar:master-panel-list'; sidebarObj.component = document.location.href; // Initialize the display var sidebar_element = document.getElementById('sidebar-box'); var sidebar_menuitem = document.getElementById('menu_sidebar'); if (sidebar_element.getAttribute('hidden') == 'true') { if (sidebar_menuitem) { sidebar_menuitem.setAttribute('checked', 'false'); } } else { if (sidebar_menuitem) { sidebar_menuitem.setAttribute('checked', 'true'); } if (sidebarObj.never_built) { sidebarObj.never_built = false; debug("sidebar = " + sidebarObj); debug("sidebarObj.resource = " + sidebarObj.resource); debug("sidebarObj.datasource_uri = " + sidebarObj.datasource_uri); // Add the user's current panel choices to the template builder, // which will aggregate it with the other datasources that describe // the individual panel's title, customize URL, and content URL. var panels = document.getElementById('sidebar-panels'); panels.database.AddDataSource(RDF.GetDataSource(sidebarObj.datasource_uri)); // The stuff on the bottom var panels_bottom = document.getElementById('sidebar-panels-bottom'); panels_bottom.database.AddDataSource(RDF.GetDataSource(sidebarObj.datasource_uri)); debug("Adding observer to database."); panels.database.AddObserver(panel_observer); // XXX This is a hack to force re-display panels.setAttribute('ref', sidebarObj.resource); // XXX This is a hack to force re-display panels_bottom.setAttribute('ref', sidebarObj.resource); } sidebar_open_default_panel(100, 0); } } function sidebar_overlay_destruct() { var panels = document.getElementById('sidebar-panels'); debug("Removeing observer from database."); panels.database.RemoveObserver(panel_observer); } // Get the template for the available panels url from preferences. // Replace variables in the url: // %LOCALE% --> Application locale (e.g. en-us). // %VERSION% --> Sidebar file format version (e.g. 0.0). function get_remote_datasource_url() { var url = ''; var prefs = Components.classes['component://netscape/preferences']; if (prefs) { prefs = prefs.getService(); } if (prefs) { prefs = prefs.QueryInterface(Components.interfaces.nsIPref); } if (prefs) { try { url = prefs.CopyCharPref("sidebar.customize.all_panels.url"); url = url.replace(/%SIDEBAR_VERSION%/g, SIDEBAR_VERSION); var locale_progid = 'component://netscape/intl/nslocaleservice'; var locale = Components.classes[locale_progid].getService(); locale = locale.QueryInterface(Components.interfaces.nsILocaleService); locale = locale.GetLocaleComponentForUserAgent(); locale = locale.toLowerCase(); url = url.replace(/%LOCALE%/g, locale); debug("Remote url is " + url); } catch(ex) { debug("Unable to get remote url pref. What now? "+ex); } } return url; } function sidebar_open_default_panel(wait, tries) { var panels_top = document.getElementById('sidebar-panels'); var target = panels_top.getAttribute('open-panel-src'); var top_headers = panels_top.childNodes; debug("sidebar_open_default_panel("+wait+","+tries+")"); if (top_headers.length <= 1) { if (tries < 5) { // No children yet, try again later setTimeout('sidebar_open_default_panel('+(wait*2)+','+(tries+1)+')',wait); } else { // No panels. // XXX This should load some help page instead of about:blank. var iframe = document.getElementById('sidebar-content'); iframe.setAttribute('src', 'about:blank'); } return; } select_panel(target); } function select_panel(target) { var panels_top = document.getElementById('sidebar-panels'); var iframe = document.getElementById('sidebar-content'); var top_headers = panels_top.childNodes; debug("select_panel("+target+")"); var select_index = find_panel(top_headers, target); if (!select_index) { // Target not found. Pick the first panel by default. // It is at index 1 because the template is at index 0. debug("select_panel: target not found, choosing last panel, index "+top_headers.length+"\n"); select_index = pick_default_panel(top_headers); target = top_headers.item(select_index).getAttribute('iframe-src'); } // Update the content area if necessary. if (iframe.getAttribute('src') != target) { iframe.setAttribute('src', target); } if (panels_top.getAttribute('open-panel-src') != target) { panels_top.setAttribute('open-panel-src', target); } update_headers(select_index); } function find_panel(panels, target) { if (target && target != '') { // Find the index of the selected panel for (var ii=1; ii < panels.length; ii++) { var item = panels.item(ii); if (item.getAttribute('iframe-src') == target) { if (is_excluded(item)) { debug("find_panel: Found panel at index, "+ii+", but it is excluded"); return 0; } else { // Found it! debug("find_panel: Found panel at index, "+ii); return ii; } } } } return 0; } function pick_default_panel(panels) { last_non_excluded_index = null; for (var ii=1; ii < panels.length; ii++) { if (!is_excluded(panels.item(ii))) { last_non_excluded_index = ii; } } return last_non_excluded_index; } function is_excluded(item) { var exclude = item.getAttribute('exclude'); var src = item.getAttribute('iframe-src'); debug("src="+src); debug("exclude="+exclude); return exclude && exclude != '' && exclude.indexOf(sidebarObj.component) != -1; } function update_headers(index) { var top_headers = document.getElementById('sidebar-panels').childNodes; var bottom_headers = document.getElementById('sidebar-panels-bottom').childNodes; for (var ii=1; ii < top_headers.length; ii++) { var top_item = top_headers.item(ii); var bottom_item = bottom_headers.item(ii); if (is_excluded(top_item)) { top_item.setAttribute('hidden','true'); bottom_item.setAttribute('hidden','true'); } else if (ii < index) { top_item.removeAttribute('selected'); top_item.removeAttribute('hidden'); bottom_item.setAttribute('hidden','true'); } else if (ii == index) { top_item.setAttribute('selected','true'); top_item.removeAttribute('hidden'); bottom_item.setAttribute('hidden','true'); } else { top_item.setAttribute('hidden','true'); bottom_item.removeAttribute('hidden'); bottom_item.removeAttribute('selected'); } } } // Change the sidebar content to the selected panel. // Called when a panel title is clicked. function SidebarSelectPanel(titledbutton) { var target = titledbutton.getAttribute('iframe-src'); var last_src = titledbutton.parentNode.getAttribute('open-panel-src'); if (target == last_src) { // XXX Maybe this should reload the content? return; } select_panel(target); } // No one is calling this right now. function SidebarReload() { sidebar_open_default_panel(100, 0); } // Set up a lame hack to avoid opening two customize // windows on a double click. var gDisableCustomize = false; function enable_customize() { gDisableCustomize = false; } // Bring up the Sidebar customize dialog. function SidebarCustomize() { // Use a single sidebar customize dialog var cwindowManager = Components.classes['component://netscape/rdf/datasource?name=window-mediator'].getService(); var iwindowManager = Components.interfaces.nsIWindowMediator; var windowManager = cwindowManager.QueryInterface(iwindowManager); var customizeWindow = windowManager.getMostRecentWindow('sidebar:customize'); if (customizeWindow) { debug("Reuse existing customize dialog"); customizeWindow.focus(); } else { debug("Open a new customize dialog"); if (false == gDisableCustomize) { gDisableCustomize = true; var panels = document.getElementById('sidebar-panels'); customizeWindow = window.openDialog( 'chrome://sidebar/content/customize.xul', '_blank','chrome,resizable', sidebarObj.master_datasources, sidebarObj.master_resource, sidebarObj.datasource_uri, sidebarObj.resource); setTimeout(enable_customize, 2000); } } } // Show/Hide the entire sidebar. // Envoked by the "View / Sidebar" menu option. function SidebarShowHide() { var sidebarBox = document.getElementById('sidebar-box'); var sidebar_splitter = document.getElementById('sidebar-splitter'); var is_hidden = sidebarBox.getAttribute('hidden'); if (is_hidden && is_hidden == "true") { debug("Showing the sidebar"); sidebarBox.removeAttribute('hidden'); sidebar_splitter.removeAttribute('hidden'); sidebar_overlay_init(); } else { debug("Hiding the sidebar"); sidebarBox.setAttribute('hidden','true'); sidebar_splitter.setAttribute('hidden','true'); } // Immediately save persistent values document.persist('sidebar-box', 'hidden'); persist_width(); } // SidebarExpandCollapse() - Respond to grippy click. // XXX This whole function is a hack to work around // bugs #20546, and #22214. function SidebarExpandCollapse() { var sidebarBox = document.getElementById('sidebar-box'); var sidebar_splitter = document.getElementById('sidebar-splitter'); sidebarBox.setAttribute('hackforbug20546-applied','true'); // Get the current open/collapsed state // The value of state is the "preclick" state var state = sidebar_splitter.getAttribute('state'); if (state && state == 'collapsed') { // Going from collapsed to open. sidebarBox.removeAttribute('hackforbug20546'); // Reset the iframe's src to get the content to display. // This might be bug #22214. var panels = document.getElementById('sidebar-panels'); var target = panels.getAttribute('open-panel-src'); var iframe = document.getElementById('sidebar-content'); iframe.setAttribute('src', target); // XXX Partial hack workaround for bug #22214. bump_width(+1); setTimeout("bump_width(-1)",10); } else { // Going from open to collapsed. sidebarBox.setAttribute('hackforbug20546','true'); } } // XXX Partial hack workaround for bug #22214. function bump_width(delta) { var sidebarBox = document.getElementById('sidebar-box'); var width = sidebarBox.getAttribute('width'); sidebarBox.setAttribute('width', parseInt(width) + delta); } function PersistHeight() { // XXX Mini hack. Persist isn't working too well. Force the persist, // but wait until the last drag has been committed. // May want to do something smarter here like only force it if the // width has really changed. setTimeout("document.persist('sidebar-panels-box','height');",100); } function persist_width() { // XXX Partial workaround for bug #19488. var sidebarBox = document.getElementById('sidebar-box'); var sidebar_splitter = document.getElementById('sidebar-splitter'); var state = sidebar_splitter.getAttribute('state'); var width = sidebarBox.getAttribute('width'); if (!state || state == '' || state == 'open') { sidebarBox.removeAttribute('hackforbug20546'); sidebarBox.setAttribute('hackforbug20546-applied','true'); } if (width && (width > 410 || width < 15)) { sidebarBox.setAttribute('width',168); } document.persist('sidebar-box', 'width'); } function SidebarFinishDrag() { // XXX Semi-hack for bug #16516. // If we had the proper drag event listener, we would not need this // timeout. The timeout makes sure the width is written to disk after // the sidebar-box gets the newly dragged width. setTimeout("persist_width()",100); } /*================================================== // Handy debug routines //================================================== function dump_attributes(node,depth) { var attributes = node.attributes; var indent = "| | | | | | | | | | | | | | | | | | | | | | | | | | | | | . "; if (!attributes || attributes.length == 0) { debug(indent.substr(indent.length - depth*2) + "no attributes"); } for (var ii=0; ii < attributes.length; ii++) { var attr = attributes.item(ii); debug(indent.substr(indent.length - depth*2) + attr.name +"="+attr.value); } } function dump_tree(node, depth) { if (!node) { debug("dump_tree: node is null"); } var indent = "| | | | | | | | | | | | | | | | | | | | | | | | | | | | | + "; debug(indent.substr(indent.length - depth*2) + node.nodeName); if (node.nodeName != "#text") { //debug(" id="+node.getAttribute('id')); dump_attributes(node, depth); } var kids = node.childNodes; for (var ii=0; ii < kids.length; ii++) { dump_tree(kids[ii], depth + 1); } } //================================================== // end of handy debug routines //==================================================*/ // Install our load handler addEventListener("load", sidebar_overlay_init, false); addEventListener("unload", sidebar_overlay_destruct, false);