home *** CD-ROM | disk | FTP | other *** search
/ PC World 2003 May / PCWorld_2003-05_cd.bin / Komunik / phoenix / chrome / toolkit.jar / content / global / widgetStateManager.js < prev    next >
Text File  |  2000-09-13  |  17KB  |  447 lines

  1. /* -*- Mode: Java; tab-width: 2; c-basic-offset: 2; -*-
  2.  * 
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  *
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  *
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  *
  18.  * Contributor(s):
  19.  *   Ben "Count XULula" Goodger <rgoodger@ihug.co.nz>
  20.  *   Alec Flett <alecf@netscape.com>
  21.  */
  22.  
  23.  
  24. /** class WizardStateManager ( string frame_id, object pageMap )
  25.  *  - purpose: object for managing data in iframe multi-panel dialogs.
  26.  *  - in: string frame id/name set of iframe, pageMap showing navigation of wizard
  27.  *  - out: nothing (object)
  28.  **/
  29. function WidgetStateManager( frame_id, panelPrefix, panelSuffix )
  30. {
  31.   // data members
  32.   /**
  33.    *  hash table for data values:
  34.    *    page1  =>  id1  =>  value1
  35.    *    page1  =>  id2  =>  value2
  36.    *    page2  =>  id1  =>  value1
  37.    *    page2  =>  id2  =>  value2
  38.    **/
  39.   this.PageData          = [];
  40.   this.content_frame     = window.frames[frame_id];
  41.  
  42.   this.panelPrefix       = ( panelPrefix ) ? panelPrefix : null;
  43.   this.panelSuffix       = ( panelSuffix ) ? panelSuffix : null;
  44.   
  45.   // member functions
  46.   this.SavePageData      = WSM_SavePageData;
  47.   this.SetPageData       = WSM_SetPageData;
  48.   this.PageIsValid       = WSM_PageIsValid;
  49.   this.GetTagFromURL     = WSM_GetTagFromURL;
  50.   this.GetURLFromTag     = WSM_GetURLFromTag;
  51.   this.toString          = WSM_toString;
  52.   this.AddAttributes     = WSM_AddAttributes;
  53.   this.ElementIsIgnored  = WSM_ElementIsIgnored;
  54.   this.HasValidElements  = WSM_HasValidElements;
  55.   this.LookupElement     = WSM_LookupElement;
  56.   this.GetDataForTag     = WSM_GetDataForTag;
  57.   this.SetDataForTag     = WSM_SetDataForTag;
  58. }
  59.  
  60. /** void SavePageData() ;
  61.  *  - purpose: retrieves form/widget data from a generic page stored in a frame.
  62.  *  -          useful for retrieving and persisting wizard/prefs page data that
  63.  *  -          has not been added to permanent storage. 
  64.  *  -          for full reference, please refer to user manual at:
  65.  *  -            http://www.mozilla.org/xpapps/ui/wizards.html
  66.  *  - in:  nothing
  67.  *  - out: nothing
  68.  **/               
  69. function WSM_SavePageData( currentPageTag, optAttributes, exclElements, inclElements )
  70. {
  71.   // 11/26/99: changing this to support the saving of an optional number of extra
  72.   // attributes other than the default value. these attributes are specified as 
  73.   // strings in an array passed in as the second parameter. these values are stored
  74.   // in the table associated with the element:
  75.   // 
  76.   // this.wsm.PageData[pageTag][element][id]    - id of element       (default)
  77.   // this.wsm.PageData[pageTag][element][value] - value of element    (default)
  78.   // this.wsm.PageData[pageTag][element][foo]   - optional attribute  (default)
  79.   // 11/27/99: changing this to support the exclusion of specified elements.
  80.   // typically this is includes fieldsets, legends and labels. These are default
  81.   // and do not need to be passed. 
  82.   
  83.   if( !currentPageTag )
  84.     currentPageTag = this.GetTagFromURL( this.content_frame.location.href, this.panelPrefix, this.panelSuffix, true );
  85.   
  86.   var doc = this.content_frame.document;
  87.   var thisTagData = this.GetDataForTag(currentPageTag);
  88.  
  89.   if( this.content_frame.GetFields ) {
  90.     // user GetFields function
  91.     this.SetDataForTag(currentPageTag, this.content_frame.GetFields());
  92.     var string = "";
  93.     for( var i in thisTagData )
  94.     {
  95.       string += "element: " + i + "\n";
  96.     }
  97.   }
  98.   else if (doc && doc.controls) {
  99.     var fields = doc.controls;
  100.     var data = [];
  101.     for( i = 0; i < fields.length; i++ ) 
  102.     { 
  103.       data[i] = []; 
  104.       var formElement = fields[i];
  105.       var elementEntry = thisTagData[formElement.id] = [];
  106.  
  107.       // check to see if element is excluded
  108.       if( !this.ElementIsIgnored( formElement, exclElements ) )
  109.         elementEntry.excluded = false;
  110.       else 
  111.         elementEntry.excluded = true;
  112.  
  113.       if( formElement.localName.toLowerCase() == "select" ) { // select & combo
  114.         /* commenting out until select fields work properly, or someone tells me how
  115.            to do this (also, is it better to store .value, or .text?):*/
  116.           if( formElement.getAttribute("multiple") ) {
  117.             // multiple selections
  118.             for( var j = 0, idx = 0; j < formElement.options.length; j++ )
  119.             {
  120.               if( formElement.options[j].selected ) {
  121.                 elementEntry.value[idx] = formElement.options[j].value;
  122.                 idx++;
  123.               }
  124.             }
  125.           }
  126.           else {
  127.               // single selections
  128.               if (formElement.options[formElement.selectedIndex]) {
  129.                   var value = formElement.options[formElement.selectedIndex].value;
  130.                   dump("*** VALUE=" + value + "\n");
  131.                   formElement.arbitraryvalue = value;
  132.                   this.AddAttributes( formElement, elementEntry, "arbitraryvalue", optAttributes );
  133.                   this.AddAttributes( formElement, elementEntry, "value", optAttributes);
  134.               }
  135.           }
  136.       }
  137.       else if( formElement.getAttribute("type") &&
  138.                ( formElement.type.toLowerCase() == "checkbox" ||
  139.                  formElement.type.toLowerCase() == "radio" ) ) {
  140.         // XXX 11/04/99
  141.         this.AddAttributes( formElement, elementEntry, "checked", optAttributes );
  142.       }
  143.       else if( formElement.type == "text" &&
  144.                formElement.getAttribute( "datatype" ) == "nsIFileSpec" &&
  145.                formElement.value ) {
  146.         try {
  147.           var filespec = Components.classes["@mozilla.org/filespec;1"].createInstance();
  148.           filespec = filespec.QueryInterface( Components.interfaces.nsIFileSpec );
  149.         }
  150.         catch(e) {
  151.           dump("*** Failed to create filespec object\n");
  152.         }
  153.         filespec.nativePath = formElement.value;
  154.         this.AddAttributes( formElement, elementEntry, "filespec", optAttributes )
  155.       }
  156.       else
  157.         this.AddAttributes( formElement, elementEntry, "value", optAttributes );  // generic
  158.  
  159.       elementEntry.id       = formElement.id;
  160.       elementEntry.localName = formElement.localName;
  161.       // save the type attribute on the element if one is present
  162.       elementEntry.elType   = ( formElement.type ) ? formElement.type : null;
  163.     }
  164.   }
  165.   if( !this.HasValidElements( thisTagData ) )
  166.     thisTagData.noData = true; // page has no (valid) elements
  167. }
  168.  
  169. /** void SetPageData() ;
  170.  *  - purpose: populates the loaded page with appropriate data from the data 
  171.  *  -          table.
  172.  *  -          for full reference, please refer to user manual at:
  173.  *  -            http://www.mozilla.org/xpapps/ui/wizards.html
  174.  *  - in:  nothing.
  175.  *  - out: nothing.
  176.  **/
  177. function WSM_SetPageData( currentPageTag, hasExtraAttributes )
  178. {
  179.   if( !currentPageTag )
  180.     currentPageTag = this.GetTagFromURL( this.content_frame.location.href, this.panelPrefix, this.panelSuffix, true );
  181.   
  182.     var doc = this.content_frame.document;
  183.   var thisTagData = this.GetDataForTag(currentPageTag);
  184.   if ( thisTagData && !thisTagData.nodata) {
  185.       for( var i in thisTagData ) {
  186.       if( thisTagData[i].excluded || !i )
  187.         continue;     // element is excluded, goto next
  188.      
  189.       var id    = thisTagData[i].id;
  190.       var value = thisTagData[i].value;
  191.  
  192.       dump("*** id & value: " + id + " : " + value + "\n");
  193.       
  194.       if( this.content_frame.SetFields && !hasExtraAttributes )
  195.         this.content_frame.SetFields( id, value );  // user provided setfields
  196.       else if( this.content_frame.SetFields && hasExtraAttributes )
  197.         this.content_frame.SetFields( id, value, thisTagData[i]); // SetFields + attrs
  198.       else {                              // automated data provision
  199.         var formElement = doc.getElementById( i );
  200.         
  201.         if( formElement && hasExtraAttributes ) {        // if extra attributes are set, set them
  202.           for( var attName in thisTagData[i] ) 
  203.           {
  204.             // for each attribute set for this element
  205.             if( attName == "value" || attName == "id" )
  206.               continue;                   // don't set value/id (value = default, id = dangerous)
  207.             var attValue  = thisTagData[i][attName];
  208.             formElement.setAttribute( attName, attValue );
  209.           }
  210.         }
  211.         
  212.         // default "value" attributes        
  213.         if( formElement && formElement.localName.toLowerCase() == "input" ) {
  214.           if( formElement.type.toLowerCase() == "checkbox" ||
  215.               formElement.type.toLowerCase() == "radio" ) {
  216.             if( value == undefined )
  217.               formElement.checked = formElement.defaultChecked;
  218.             else 
  219.               formElement.checked = value;
  220. /*            oops.. appears we've reimplemented 'reversed'. this will be why its not working for alecf. 
  221.               if( formElement.getAttribute( "reversed" ) )
  222.                 formElement.checked = !value;
  223.               else
  224.                 formElement.checked = value;
  225.                 */
  226.           }
  227.           else if( formElement.type.toLowerCase() == "text" &&
  228.                formElement.getAttribute( "datatype" ) == "nsIFileSpec" ) {
  229.             // formElement has something to do with fileSpec. looked important
  230.             if( value ) {
  231.               var filespec = value.QueryInterface( Components.interfaces.nsIFileSpec );
  232.               try {
  233.                 formElement.value = filespec.nativePath;
  234.               } 
  235.               catch( ex ) {
  236.                 dump("Still need to fix uninitialized filespec problem!\n");
  237.               }
  238.             } 
  239.             else
  240.               formElement.value = formElement.defaultValue;
  241.           }
  242.           else {                          // some other type of form element
  243.             if( value == undefined )
  244.               formElement.value = formElement.defaultValue;
  245.             else
  246.               formElement.value = value;
  247.           }
  248.         } 
  249.         else if( formElement && formElement.localName.toLowerCase() == "select" ) {
  250.           /* commenting this out until select widgets work properly */
  251.             if( formElement.getAttribute("multiple") &&
  252.                 typeof(value) == "object" ) {
  253.               // multiple selected items
  254.               for( var j = 0; j < value.length; j++ )
  255.               {
  256.                 for ( var k = 0; k < formElement.options.length; k++ )
  257.                 {
  258.                   if( formElement.options[k].value == value[j] )
  259.                     formElement.options[k].selected = true;
  260.                 }
  261.               }
  262.             }
  263.             else {
  264.               // single selected item
  265.               for ( k = 0; k < formElement.options.length; k++ )
  266.               {
  267.                 dump("*** value=" + value + "; options[k].value=" + formElement.options[k].value + "\n");
  268.                 if( formElement.options[k].value == value )
  269.                   formElement.options[k].selected = true;
  270.               }
  271.             }            
  272.         }
  273.         else if( formElement && formElement.localName.toLowerCase() == "textarea" )
  274.           formElement.value = value;
  275.       }
  276.     }
  277.   }
  278.   // initialize the pane
  279.   if (this.content_frame.onInit) {
  280.     dump("Calling custom onInit()\n");
  281.     this.content_frame.onInit();
  282.   }
  283.     
  284. }   
  285.  
  286. /** boolean PageIsValid()
  287.  * - purpose: returns whether the given page is in a valid state
  288.  * - in:
  289.  * - out: 
  290.  */
  291. function WSM_PageIsValid()
  292. {
  293.   if( this.content_frame.validate )
  294.     return this.content_frame.validate();
  295.  
  296.   // page is valid by default
  297.   return true;
  298. }
  299.  
  300.  
  301. /** string GetTagFromURL( string tag, string prefix, string postfix ) ;
  302.  *  - purpose: fetches a tag from a URL
  303.  *  - in:   string url representing the complete location of the page.
  304.  *  - out:  string tag representing the specific page to be loaded
  305.  **/               
  306. function WSM_GetTagFromURL( url, prefix, suffix, mode )
  307. {
  308.   // NOTE TO SELF: this is an accident WAITING to happen
  309.   if (!prefix) return undefined;
  310.   if( mode )
  311.     return url.substring( prefix.length, url.lastIndexOf(suffix) );
  312.   else
  313.     return url.substring( url.lastIndexOf(prefix) + 1, url.lastIndexOf(suffix) );
  314. }
  315.  
  316. /** string GetUrlFromTag( string tag, string prefix, string postfix ) ;
  317.  *  - purpose: creates a complete URL based on a tag.
  318.  *  - in:  string tag representing the specific page to be loaded
  319.  *  - out: string url representing the complete location of the page.
  320.  **/               
  321. function WSM_GetURLFromTag( tag, prefix, postfix ) 
  322. {
  323.   return prefix + tag + postfix;
  324. }
  325.  
  326. /** string toString() ;
  327.  *  - purpose: returns a string representation of the object
  328.  *  - in: nothing;
  329.  *  - out: nothing;
  330.  **/
  331. function WSM_toString()
  332. {
  333.   var string = "";
  334.   for( var i in this.PageData ) {
  335.     for( var j in this.PageData[i] ) {
  336.       for( var k in this.PageData[i][j] ) {
  337.         string += "WSM.PageData[" + i + "][" + j + "][" + k + "] : " + this.PageData[i][j][k] + ";\n";
  338.       }
  339.     }
  340.   }
  341.   return string;
  342. }
  343.  
  344. /** void AddAttributes( DOMElement formElement, AssocArray elementEntry, 
  345.                         String valueAttribute, StringArray optAttributes ) ;
  346.  *  - purpose: adds name/value entries to associative array.
  347.  *  - in:       formElement - element to add attributes from
  348.  *  -           elementEntry - the associative array to add data to
  349.  *  -           valueAttribute - string representing which attribute represents 
  350.  *  -               value (e.g. "value", "checked")
  351.  *  -           optAttributes - array of extra attributes to store. 
  352.  *  - out: nothing;
  353.  **/
  354. function WSM_AddAttributes( formElement, elementEntry, valueAttribute, optAttributes )
  355. {
  356.   // 07/01/00 adding in a reversed thing here for alecf's ultra picky mail prefs :P:P
  357.   if( formElement.getAttribute("reversed") )
  358.     elementEntry.value = !formElement[valueAttribute]; // get the value (e.g. "checked")
  359.   else
  360.     elementEntry.value = formElement[valueAttribute]; // get the value (e.g. "checked")
  361.   
  362.   if( optAttributes ) {   // if we've got optional attributes, add em
  363.     for(var k = 0; k < optAttributes.length; k++ ) 
  364.     {
  365.       attValue = formElement.getAttribute( optAttributes[k] );
  366.       if( attValue )
  367.         elementEntry[optAttributes[k]] = attValue;
  368.     }
  369.   }
  370. }
  371.  
  372. /** string ElementIsIgnored( DOMElement element, StringArray exclElements ) ;
  373.  *  - purpose: check to see if the current element is one of the ignored elements
  374.  *  - in:       element - element to check, 
  375.  *  -           exclElements - array of string ignored attribute localNames;
  376.  *  - out:      boolean if element is ignored (true) or not (false);
  377.  **/
  378. function WSM_ElementIsIgnored( element, exclElements )
  379. {
  380.   if (!exclElements) return false;
  381.   for( var i = 0; i < exclElements.length; i++ )
  382.   {
  383.     if( element.localName.toLowerCase() == exclElements[i] )
  384.       return true;
  385.   }
  386.   return false;
  387. }
  388.  
  389. /** string HasValidElements( AssocArray dataStore ) ;
  390.  *  - purpose:  checks to see if there are any elements on this page that are 
  391.  *  -           valid.
  392.  *  - in:       associative array representing the page;
  393.  *  - out:      boolean whether or not valid elements are present (true) or not (false);
  394.  **/
  395. function WSM_HasValidElements( dataStore )
  396. {
  397.   for( var i in dataStore ) 
  398.   {
  399.     if( !dataStore[i].excluded )
  400.       return true;
  401.   }
  402.   return false;
  403. }
  404.  
  405.  
  406. function WSM_LookupElement( element, lookby, property )
  407. {
  408.   for(var i in this.PageData )
  409.   {
  410.     for( var j in this.PageData[i] )
  411.     {
  412.       if(!lookby) 
  413.         lookby = "id";    // search by id by default
  414.       if( j[lookby] == element && !property )
  415.         return j;
  416.       else if( j[lookby] == element ) {
  417.         var container = [];
  418.         for( var k = 0; k < property.length; k++ )
  419.         {
  420.           container[k] = this.PageData[i][k][property[k]];
  421.         }
  422.         return container; // only support one single match per hash just now
  423.       }
  424.     }
  425.   }
  426.   return undefined;
  427. }
  428.  
  429. /**
  430.  * array GetDataForTag(string tag)
  431.  * - purpose: to get the array associated with this tag
  432.  *            creates the array if one doesn't already exist
  433.  * - in:      tag
  434.  * - out:     the associative array for this page
  435.  */
  436. function WSM_GetDataForTag(tag) {
  437.   if (!this.PageData[tag])
  438.     this.PageData[tag] = [];
  439.   return this.PageData[tag];
  440. }
  441.  
  442. function WSM_SetDataForTag(tag, data) {
  443.   this.PageData[tag] = data;
  444. }
  445.  
  446. /* it will be dark soon */
  447.