2002-10-19 19:38:57 +00:00
# - * - Mode : Java ; tab - width : 4 ; indent - tabs - mode : nil ; c - basic - offset : 2 - * -
# * * * * * BEGIN LICENSE BLOCK * * * * *
# Version : NPL 1.1 / GPL 2.0 / LGPL 2.1
#
# The contents of this file are subject to the Netscape 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/NPL/
#
# 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 . org code .
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation . Portions created by Netscape are
# Copyright ( C ) 1998 Netscape Communications Corporation . All
# Rights Reserved .
#
# Contributor ( s ) : smorrison @ gte . com
# Terry Hayes < thayes @ netscape . com >
# Daniel Brooks < db48x @ yahoo . com >
#
# Alternatively , the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later ( the "GPL" ) , or
# the GNU Lesser General Public License Version 2.1 or later ( the "LGPL" ) ,
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above . If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL , and not to allow others to
# use your version of this file under the terms of the NPL , indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL . If you do not delete
# the provisions above , a recipient may use your version of this file under
# the terms of any one of the NPL , the GPL or the LGPL .
#
# * * * * * END LICENSE BLOCK * * * * *
//******** define a js object to implement nsITreeView
function pageInfoTreeView ( columnids , copycol )
{
// columnids is an array of strings indicating the names of the columns, in order
this . columnids = columnids ;
this . colcount = columnids . length
// copycol is the index number for the column that we want to add to
// the copy-n-paste buffer when the user hits accel-c
this . copycol = copycol ;
this . rows = 0 ;
this . tree = null ;
this . data = new Array ;
this . selection = null ;
this . sortcol = null ;
this . sortdir = 0 ;
this . initialized = 0 ; // set this to one once we fill in all the rows
}
pageInfoTreeView . prototype = {
set rowCount ( c ) { throw "rowCount is a readonly property" ; } ,
get rowCount ( ) { return this . rows ; } ,
setTree : function ( tree )
{
this . tree = tree ;
} ,
getCellText : function ( row , column )
{
var colidx = 0 ;
// loop through the list of column names to find the index to the column
// we should be worrying about. very much a hack, but what can you do?
while ( colidx < this . colcount && column != this . columnids [ colidx ] )
colidx ++ ;
// row can be null, but js arrays are 0-indexed.
// colidx cannot be null, but can be larger than the number
// of columns in the array (when column is a string not in
// this.columnids.) In this case it's the fault of
// whoever typoed while calling this function.
return this . data [ row ] [ colidx ] || "" ;
} ,
setCellText : function ( row , column , value )
{
var colidx = 0 ;
// loop through the list of column names to find the index
// to the column the should be worrying about. very much a hack, but
// what can you do?
// XXX: I think there's a better way to do this now...
while ( colidx < this . colcount && column != this . columnids [ colidx ] )
colidx ++ ;
this . data [ row ] [ colidx ] = value ;
} ,
addRow : function ( row )
{
this . rows = this . data . push ( row ) ;
} ,
addRows : function ( rows )
{
var length = rows . length ;
for ( var i = 0 ; i < length ; i ++ )
this . rows = this . data . push ( rows [ i ] ) ;
} ,
rowCountChanged : function ( index , count )
{
this . tree . rowCountChanged ( index , count ) ;
} ,
invalidate : function ( )
{
this . tree . invalidate ( ) ;
} ,
clear : function ( )
{
this . data = new Array ;
this . rows = 0 ;
} ,
handleCopy : function ( row )
{
return ( row < 0 || copycol < 0 ) ? "" : ( this . data [ row ] [ this . copycol ] || "" ) ;
} ,
performActionOnRow : function ( action , row )
{
if ( action == "copy" )
{
var data = this . handleCopy ( row )
this . tree . treeBody . parentNode . setAttribute ( "copybuffer" , data ) ;
}
} ,
getRowProperties : function ( row , column , prop ) { } ,
getCellProperties : function ( row , prop ) { } ,
getColumnProperties : function ( column , elem , prop ) { } ,
isContainer : function ( index ) { return false ; } ,
isContainerOpen : function ( index ) { return false ; } ,
isSeparator : function ( index ) { return false ; } ,
isSorted : function ( ) { } ,
canDropOn : function ( index ) { return false ; } ,
canDropBeforeAfter : function ( index , before ) { return false ; } ,
drop : function ( row , orientation ) { return false ; } ,
getParentIndex : function ( index ) { return 0 ; } ,
hasNextSibling : function ( index , after ) { return false ; } ,
getLevel : function ( index ) { return 0 ; } ,
getImageSrc : function ( row , column ) { } ,
getProgressMode : function ( row , column ) { } ,
getCellValue : function ( row , column ) { } ,
toggleOpenState : function ( index ) { } ,
cycleHeader : function ( col , elem ) { } ,
selectionChanged : function ( ) { } ,
cycleCell : function ( row , column ) { } ,
isEditable : function ( row , column ) { return false ; } ,
performAction : function ( action ) { } ,
performActionOnCell : function ( action , row , column ) { }
} ;
// mmm, yummy. global variables.
var theWindow = null ;
var theDocument = null ;
// column number to copy from, second argument to pageInfoTreeView's constructor
const COPYCOL _NONE = - 1 ;
const COPYCOL _META _CONTENT = 1 ;
const COPYCOL _FORM _ACTION = 2 ;
const COPYCOL _LINK _ADDRESS = 1 ;
const COPYCOL _IMAGE _ADDRESS = 0 ;
// one nsITreeView for each tree in the window
var metaView = new pageInfoTreeView ( [ "meta-name" , "meta-content" ] , COPYCOL _META _CONTENT ) ;
var formView = new pageInfoTreeView ( [ "form-name" , "form-method" , "form-action" , "form-node" ] , COPYCOL _FORM _ACTION ) ;
var fieldView = new pageInfoTreeView ( [ "field-label" , "field-field" , "field-type" , "field-value" ] , COPYCOL _NONE ) ;
var linkView = new pageInfoTreeView ( [ "link-name" , "link-address" , "link-type" ] , COPYCOL _LINK _ADDRESS ) ;
var imageView = new pageInfoTreeView ( [ "image-address" , "image-type" , "image-alt" , "image-node" ] , COPYCOL _IMAGE _ADDRESS ) ;
// localized strings (will be filled in when the document is loaded)
// this isn't all of them, these are just the ones that would otherwise have been loaded inside a loop
var gStrings = { }
var theBundle ;
const DRAGSERVICE _CONTRACTID = "@mozilla.org/widget/dragservice;1" ;
const TRANSFERABLE _CONTRACTID = "@mozilla.org/widget/transferable;1" ;
const ARRAY _CONTRACTID = "@mozilla.org/supports-array;1" ;
const STRING _CONTRACTID = "@mozilla.org/supports-string;1" ;
// a number of services I'll need later
// the cache services
const nsICacheService = Components . interfaces . nsICacheService ;
const cacheService = Components . classes [ "@mozilla.org/network/cache-service;1" ] . getService ( nsICacheService ) ;
var httpCacheSession = cacheService . createSession ( "HTTP" , 0 , true ) ;
httpCacheSession . doomEntriesIfExpired = false ;
var ftpCacheSession = cacheService . createSession ( "FTP" , 0 , true ) ;
ftpCacheSession . doomEntriesIfExpired = false ;
// scriptable date formater, for pretty printing dates
const nsIScriptableDateFormat = Components . interfaces . nsIScriptableDateFormat ;
var dateService = Components . classes [ "@mozilla.org/intl/scriptabledateformat;1" ] . getService ( nsIScriptableDateFormat ) ;
// clipboard helper
try
{
const gClipboardHelper = Components . classes [ "@mozilla.org/widget/clipboardhelper;1" ] . getService ( Components . interfaces . nsIClipboardHelper ) ;
}
catch ( e )
{
// do nothing, later code will handle the error
}
// namespaces, don't need all of these yet...
const XLinkNS = "http://www.w3.org/1999/xlink" ;
const XULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" ;
const XMLNS = "http://www.w3.org/XML/1998/namespace" ;
const XHTMLNS = "http://www.w3.org/1999/xhtml" ;
/ * O v e r l a y s r e g i s t e r i n i t f u n c t i o n s h e r e .
* Add functions to call by invoking "onLoadRegistry.append(XXXLoadFunc);"
* The XXXLoadFunc should be unique to the overlay module , and will be
* invoked as "XXXLoadFunc();"
* /
var onLoadRegistry = [ ] ;
/ * C a l l e d w h e n P a g e I n f o w i n d o w i s l o a d e d . A r g u m e n t s a r e :
* window . arguments [ 0 ] - document to use for source ( null = Page Info , otherwise Frame Info )
* window . arguments [ 1 ] - tab name to display first ( may be null )
* /
function onLoadPageInfo ( )
{
//dump("===============================================================================\n");
theBundle = document . getElementById ( "pageinfobundle" ) ;
gStrings . unknown = theBundle . getString ( "unknown" ) ;
gStrings . notSet = theBundle . getString ( "notset" ) ;
gStrings . emptyString = theBundle . getString ( "emptystring" ) ;
gStrings . linkAnchor = theBundle . getString ( "linkAnchor" ) ;
gStrings . linkArea = theBundle . getString ( "linkArea" ) ;
gStrings . linkSubmit = theBundle . getString ( "linkSubmit" ) ;
gStrings . linkSubmission = theBundle . getString ( "linkSubmission" ) ;
gStrings . linkRel = theBundle . getString ( "linkRel" ) ;
gStrings . linkStylesheet = theBundle . getString ( "linkStylesheet" ) ;
gStrings . linkRev = theBundle . getString ( "linkRev" ) ;
gStrings . linkX = theBundle . getString ( "linkX" ) ;
gStrings . mediaImg = theBundle . getString ( "mediaImg" ) ;
gStrings . mediaApplet = theBundle . getString ( "mediaApplet" ) ;
gStrings . mediaObject = theBundle . getString ( "mediaObject" ) ;
gStrings . mediaEmbed = theBundle . getString ( "mediaEmbed" ) ;
gStrings . mediaLink = theBundle . getString ( "mediaLink" ) ;
gStrings . mediaInput = theBundle . getString ( "mediaInput" ) ;
var docTitle = "" ;
if ( "arguments" in window && window . arguments . length >= 1 && window . arguments [ 0 ] )
{
theWindow = null ;
theDocument = window . arguments [ 0 ] ;
docTitle = theBundle . getString ( "frameInfo.title" ) ;
}
else
{
if ( "gBrowser" in window . opener )
theWindow = window . opener . gBrowser . contentWindow ;
else
theWindow = window . opener . frames [ 0 ] ;
theDocument = theWindow . document ;
docTitle = theBundle . getString ( "pageInfo.title" ) ;
}
document . title = docTitle ;
// do the easy stuff first
makeGeneralTab ( ) ;
/* Call registered overlay init functions */
for ( x in onLoadRegistry )
{
onLoadRegistry [ x ] ( ) ;
}
/* Select the requested tab, if the name is specified */
if ( "arguments" in window && window . arguments . length > 1 )
{
var tabName = window . arguments [ 1 ] ;
if ( tabName )
{
var tabControl = document . getElementById ( "tabbox" ) ;
var tab = document . getElementById ( tabName ) ;
if ( tabControl && tab )
{
tabControl . selectedTab = tab ;
}
}
}
}
function doHelpButton ( ) {
var tabControl = document . getElementById ( "tabbox" ) ;
switch ( tabControl . selectedTab . id ) {
case "generalTab" :
helpdoc = "pageinfo_general" ;
break ;
case "formsTab" :
helpdoc = "pageinfo_forms" ;
break ;
case "linksTab" :
helpdoc = "pageinfo_links" ;
break ;
case "mediaTab" :
helpdoc = "pageinfo_media" ;
break ;
case "securityTab" :
helpdoc = "pageinfo_security" ;
break ;
case "p3pTab" :
helpdoc = "pageinfo_privacy" ;
break ;
default :
helpdoc = "pageinfo_general" ;
break ;
}
openHelp ( helpdoc ) ;
}
function makeGeneralTab ( )
{
var title = ( theDocument . title ) ? theBundle . getFormattedString ( "pageTitle" , [ theDocument . title ] ) : theBundle . getString ( "noPageTitle" ) ;
document . getElementById ( "titletext" ) . value = title ;
var url = theDocument . location ;
document . getElementById ( "urltext" ) . value = url ;
var mode = ( "compatMode" in theDocument && theDocument . compatMode == "BackCompat" ) ? theBundle . getString ( "generalQuirksMode" ) : theBundle . getString ( "generalStrictMode" ) ;
document . getElementById ( "modetext" ) . value = mode ;
var referrer = ( theDocument . referrer ) ? theDocument . referrer : theBundle . getString ( "generalNoReferrer" ) ;
document . getElementById ( 'refertext' ) . value = referrer ;
// find out the mime type
var mimeType = theDocument . contentType || gStrings . unknown ;
document . getElementById ( "typetext" ) . value = mimeType ;
// get the meta tags
var metaNodes = theDocument . getElementsByTagName ( "meta" ) ;
var metaTree = document . getElementById ( "metatree" ) ;
metaTree . treeBoxObject . view = metaView ;
var length = metaNodes . length ;
for ( var i = 0 ; i < length ; i ++ )
metaView . addRow ( [ metaNodes [ i ] . name || metaNodes [ i ] . httpEquiv , metaNodes [ i ] . content ] ) ;
metaView . rowCountChanged ( 0 , length ) ;
// get the document characterset
var encoding = theDocument . characterSet ;
document . getElementById ( "encodingtext" ) . value = encoding ;
// get the date of last modification
var modifiedText = formatDate ( theDocument . lastModified , gStrings . notSet ) ;
document . getElementById ( "modifiedtext" ) . value = modifiedText ;
// get cache info
var sourceText = theBundle . getString ( "generalNotCached" ) ;
var expirationText = theBundle . getString ( "generalNoExpiration" ) ;
var sizeText = gStrings . unknown ;
var pageSize = 0 ;
var kbSize = 0 ;
var expirationTime = 0 ;
try
{
var cacheEntryDescriptor = httpCacheSession . openCacheEntry ( url , Components . interfaces . nsICache . ACCESS _READ , false ) ;
if ( cacheEntryDescriptor )
{
switch ( cacheEntryDescriptor . deviceID )
{
case "disk" :
sourceText = theBundle . getString ( "generalDiskCache" ) ;
break ;
case "memory" :
sourceText = theBundle . getString ( "generalMemoryCache" ) ;
break ;
default :
sourceText = cacheEntryDescriptor . deviceID ;
break ;
}
pageSize = cacheEntryDescriptor . dataSize ;
kbSize = pageSize / 1024 ;
sizeText = theBundle . getFormattedString ( "generalSize" , [ Math . round ( kbSize * 100 ) / 100 , pageSize ] ) ;
expirationText = formatDate ( cacheEntryDescriptor . expirationTime * 1000 , gStrings . notSet ) ;
}
}
catch ( ex )
{
try
{
cacheEntryDescriptor = ftpCacheSession . openCacheEntry ( url , Components . interfaces . nsICache . ACCESS _READ , false ) ;
if ( cacheEntryDescriptor )
{
switch ( cacheEntryDescriptor . deviceID )
{
case "disk" :
sourceText = theBundle . getString ( "generalDiskCache" ) ;
break ;
case "memory" :
sourceText = theBundle . getString ( "generalMemoryCache" ) ;
break ;
default :
sourceText = cacheEntryDescriptor . deviceID ;
break ;
}
pageSize = cacheEntryDescriptor . dataSize ;
kbSize = pageSize / 1024 ;
sizeText = theBundle . getFormattedString ( "generalSize" , [ Math . round ( kbSize * 100 ) / 100 , pageSize ] ) ;
expirationText = formatDate ( cacheEntryDescriptor . expirationTime * 1000 , gStrings . notSet ) ;
}
}
catch ( ex2 )
{
sourceText = theBundle . getString ( "generalNotCached" ) ;
}
}
document . getElementById ( "sourcetext" ) . value = sourceText ;
document . getElementById ( "expirestext" ) . value = expirationText ;
document . getElementById ( "sizetext" ) . value = sizeText ;
}
//******** Generic Build-a-tab
function makeTabs ( aDocument , aWindow )
{
if ( formView . initialized || linkView . initialized || imageView . initialized )
return ;
if ( aWindow && aWindow . frames . length > 0 )
{
var num = aWindow . frames . length ;
for ( var i = 0 ; i < num ; i ++ )
makeTab ( aWindow . frames [ i ] . document , aWindow . frames [ i ] ) ; // recurse through the frames
}
var formTree = document . getElementById ( "formtree" ) ;
var linkTree = document . getElementById ( "linktree" ) ;
var imageTree = document . getElementById ( "imagetree" ) ;
formTree . treeBoxObject . view = formView ;
linkTree . treeBoxObject . view = linkView ;
imageTree . treeBoxObject . view = imageView ;
var iterator = aDocument . createTreeWalker ( aDocument , NodeFilter . SHOW _ELEMENT , grabAll , true ) ;
while ( iterator . nextNode ( ) )
; // it'll never be executed anyway, since grabAll never
// accepts any nodes
formView . rowCountChanged ( 0 , formView . rowCount ) ;
formView . selection . select ( 0 ) ;
formView . initialized = 1 ;
linkView . rowCountChanged ( 0 , linkView . rowCount ) ;
linkView . selection . select ( 0 ) ;
linkView . initialized = 1 ;
imageView . rowCountChanged ( 0 , imageView . rowCount ) ;
imageView . selection . select ( 0 ) ;
imageView . initialized = 1 ;
}
function grabAll ( elem )
{
// one switch to rule them all
2002-11-04 23:24:29 +00:00
// XXX: these tests should use regexes to be a little more lenient wrt whitespace, see bug 177047
2002-10-19 19:38:57 +00:00
var linktext ;
switch ( elem . nodeName . toLowerCase ( ) )
{
// form tab
case "form" :
formView . addRow ( [ elem . name , elem . method , elem . getAttribute ( "action" ) , elem ] ) ; // use getAttribute() because of bug 122128
break ;
// link tab
case "a" :
linktext = getValueText ( elem ) ;
linkView . addRow ( [ linktext , elem . href , gStrings . linkAnchor , elem . target ] ) ;
break ;
case "area" :
linkView . addRow ( [ elem . alt , elem . href , gStrings . linkArea , elem . target ] ) ;
break ;
case "input" :
linkView . addRow ( [ elem . value || gStrings . linkSubmit , elem . form . getAttribute ( "action" ) , gStrings . linkSubmission , elem . form . getAttribute ( "target" ) ] ) ; // use getAttribute() due to bug 122128
break ;
case "link" :
if ( elem . rel )
{
2002-11-04 23:24:29 +00:00
var rel = elem . rel . toLowerCase ( ) ;
2002-10-19 19:38:57 +00:00
// should this test use regexes to be a little more lenient wrt whitespace?
2002-11-04 23:24:29 +00:00
if ( rel == "icon" ) {
imageView . addRow ( [ elem . href , gStrings . mediaLink , "" , elem ] ) ;
break ;
}
if ( rel == "stylesheet" || rel == "alternate stylesheet" )
2002-10-19 19:38:57 +00:00
linktext = gStrings . linkStylesheet ;
else
linktext = gStrings . linkRel ;
}
else
linktext = gStrings . linkRev ;
linkView . addRow ( [ elem . rel || elem . rev , elem . href , linktext , elem . target ] ) ;
break ;
// media tab
case "img" :
imageView . addRow ( [ elem . src , gStrings . mediaImg , ( elem . hasAttribute ( "alt" ) ) ? elem . alt : gStrings . notSet , elem ] ) ;
break ;
case "input" :
if ( elem . type == "image" )
imageView . addRow ( [ elem . src , gStrings . mediaInput , ( elem . hasAttribute ( "alt" ) ) ? elem . alt : gStrings . notSet , elem ] ) ;
break ;
case "applet" :
//XXX When Java is enabled, the DOM model for <APPLET> is broken. Bug #59686.
// Also, some reports of a crash with Java in Media tab (bug 136535), and mixed
// content from two hosts (bug 136539) so just drop applets from Page Info when
// Java is on. For the 1.0.1 branch; get a real fix on the trunk.
if ( ! navigator . javaEnabled ( ) )
imageView . addRow ( [ elem . code || elem . object , gStrings . mediaApplet , "" , elem ] ) ;
break ;
case "object" :
imageView . addRow ( [ elem . data , gStrings . mediaObject , getValueText ( elem ) , elem ] ) ;
break ;
case "embed" :
imageView . addRow ( [ elem . src , gStrings . mediaEmbed , "" , elem ] ) ;
break ;
default :
if ( elem . hasAttributeNS ( XLinkNS , "href" ) )
{
linktext = getValueText ( elem ) ;
linkView . addRow ( [ linktext , elem . href , gStrings . linkX , "" ] ) ;
}
break ;
}
return NodeFilter . FILTER _SKIP ;
}
//******** Form Stuff
function onFormSelect ( )
{
var formTree = document . getElementById ( "formtree" ) ;
if ( ! formView . rowCount ) return ;
if ( formView . selection . count == 1 )
{
var formPreview = document . getElementById ( "formpreview" ) ;
fieldView . clear ( ) ;
formPreview . treeBoxObject . view = fieldView ;
var clickedRow = formView . selection . currentIndex ;
var form = formView . getCellText ( clickedRow , "form-node" ) ;
var ft = null ;
if ( form . name )
ft = theBundle . getFormattedString ( "formTitle" , [ form . name ] ) ;
else
ft = theBundle . getString ( "formUntitled" ) ;
document . getElementById ( "formname" ) . value = ft || theBundle . getString ( "formUntitled" ) ;
document . getElementById ( "formenctype" ) . value = form . encoding || theBundle . getString ( "default" ) ;
document . getElementById ( "formtarget" ) . value = form . target || theBundle . getString ( "formDefaultTarget" ) ;
var formfields = form . elements ;
var length = formfields . length ;
var i = 0 ;
var checked = theBundle . getString ( "formChecked" ) ;
var unchecked = theBundle . getString ( "formUnchecked" ) ;
for ( i = 0 ; i < length ; i ++ )
{
var elem = formfields [ i ] ;
if ( elem . nodeName . toLowerCase ( ) == "button" )
fieldView . addRow ( [ "" , elem . name , elem . type , getValueText ( elem ) ] ) ;
else
{
var val = ( elem . type == "password" ) ? theBundle . getString ( "formPassword" ) : elem . value ;
fieldView . addRow ( [ "" , elem . name , elem . type , val ] ) ;
}
}
var labels = form . getElementsByTagName ( "label" ) ;
var llength = labels . length ;
for ( i = 0 ; i < llength ; i ++ )
{
var whatfor = labels [ i ] . hasAttribute ( "for" ) ?
theDocument . getElementById ( labels [ i ] . getAttribute ( "for" ) ) :
findFirstControl ( labels [ i ] ) ;
if ( whatfor && ( whatfor . form == form ) ) {
var labeltext = getValueText ( labels [ i ] ) ;
for ( var j = 0 ; j < length ; j ++ )
if ( formfields [ j ] == whatfor )
fieldView . setCellText ( j , "field-label" , labeltext ) ;
}
}
fieldView . rowCountChanged ( 0 , length ) ;
}
}
function findFirstControl ( node )
{
function FormControlFilter ( )
{
switch ( node . nodeName . toLowerCase ( ) )
{
case "input" :
case "select" :
case "button" :
case "textarea" :
case "object" :
return NodeFilter . FILTER _ACCEPT ;
default :
return NodeFilter . FILTER _SKIP ;
}
}
var iterator = theDocument . createTreeWalker ( node , NodeFilter . SHOW _ELEMENT , FormControlFilter , true ) ;
return iterator . nextNode ( ) ;
}
//******** Link Stuff
function openURL ( target )
{
var url = target . parentNode . childNodes [ 2 ] . value ;
window . open ( url , "_blank" , "chrome" ) ;
}
function onBeginLinkDrag ( event , urlField , descField )
{
if ( event . originalTarget . localName != "treechildren" )
return ;
var tree = event . target ;
if ( ! ( "treeBoxObject" in tree ) )
tree = tree . parentNode ;
var row = { } ;
var col = { } ;
var elt = { } ;
tree . treeBoxObject . getCellAt ( event . clientX , event . clientY , row , col , elt ) ;
if ( row . value == - 1 )
return ;
// Getting drag-system needed services
var dragService = Components . classes [ DRAGSERVICE _CONTRACTID ] . getService ( ) . QueryInterface ( Components . interfaces . nsIDragService ) ;
var transArray = Components . classes [ ARRAY _CONTRACTID ] . createInstance ( Components . interfaces . nsISupportsArray ) ;
if ( ! transArray )
return ;
var trans = Components . classes [ TRANSFERABLE _CONTRACTID ] . createInstance ( Components . interfaces . nsITransferable ) ;
if ( ! trans )
return ;
// Adding URL flavor
trans . addDataFlavor ( "text/x-moz-url" ) ;
var url = tree . treeBoxObject . view . getCellText ( row . value , urlField ) ;
var desc = tree . treeBoxObject . view . getCellText ( row . value , descField ) ;
var stringURL = Components . classes [ STRING _CONTRACTID ] . createInstance ( Components . interfaces . nsISupportsString ) ;
stringURL . data = url + "\n" + desc ;
trans . setTransferData ( "text/x-moz-url" , stringURL , stringURL . data . length * 2 ) ;
transArray . AppendElement ( trans . QueryInterface ( Components . interfaces . nsISupports ) ) ;
dragService . invokeDragSession ( event . target , transArray , null , dragService . DRAGDROP _ACTION _NONE ) ;
}
//******** Image Stuff
function getSource ( item )
{
// Return the correct source without strict warnings
if ( item . href != null )
return item . href ;
if ( item . src != null )
return item . src ;
return null ;
}
function getSelectedImage ( tree )
{
if ( ! imageView . rowCount ) return null ;
// Only works if only one item is selected
var clickedRow = tree . treeBoxObject . selection . currentIndex ;
return imageView . getCellText ( clickedRow , "image-node" ) ;
}
function saveMedia ( )
{
var tree = document . getElementById ( "imagetree" ) ;
2002-11-04 23:21:20 +00:00
var item = getSelectedImage ( tree ) ;
2002-10-19 19:38:57 +00:00
var url = getAbsoluteURL ( getSource ( item ) , item ) ;
if ( url )
saveURL ( url , null , 'SaveImageTitle' , false ) ;
}
function onImageSelect ( )
{
var tree = document . getElementById ( "imagetree" ) ;
var saveAsButton = document . getElementById ( "imagesaveasbutton" ) ;
if ( tree . treeBoxObject . selection . count == 1 )
{
makePreview ( getSelectedImage ( tree ) ) ;
saveAsButton . setAttribute ( "disabled" , "false" ) ;
}
else
saveAsButton . setAttribute ( "disabled" , "true" ) ;
}
function makePreview ( item )
{
var url = ( "src" in item && item . src ) || ( "code" in item && item . code )
|| ( "data" in item && item . data ) || ( "href" in item && item . href )
|| gStrings . unknown ; // it better have at least one of those...
document . getElementById ( "imageurltext" ) . value = url ;
document . getElementById ( "imagetitletext" ) . value = item . title || gStrings . notSet ;
var altText = null ;
if ( item . hasAttribute ( "alt" ) && ( "alt" in item ) )
altText = item . alt ;
else if ( item . hasChildNodes ( ) )
altText = getValueText ( item ) ;
if ( altText == null )
altText = gStrings . notSet ;
var textbox = document . getElementById ( "imagealttext" ) ;
// IMO all text that is not really the value text should go in italics
// What if somebody has <img alt="Not specified">? =)
// We can't use textbox.style because of bug 7639
if ( altText == "" ) {
textbox . value = gStrings . emptyString ;
textbox . setAttribute ( "style" , "font-style:italic" ) ;
} else {
textbox . value = altText ;
textbox . setAttribute ( "style" , "font-style:inherit" ) ;
}
document . getElementById ( "imagelongdesctext" ) . value = ( "longDesc" in item && item . longDesc ) || gStrings . notSet ;
// find out the mime type
var mimeType = gStrings . unknown ;
if ( item . nodeName . toLowerCase ( ) != "input" )
mimeType = ( "type" in item && item . type ) || ( "codeType" in item && item . codeType )
|| ( "contentType" in item && item . contentType ) || gStrings . unknown ;
document . getElementById ( "imagetypetext" ) . value = mimeType ;
// get cache info
var sourceText = theBundle . getString ( "generalNotCached" ) ;
var expirationText = gStrings . unknown ;
var sizeText = gStrings . unknown ;
var pageSize = 0 ;
var kbSize = 0 ;
var expirationTime = 0 ;
var expirationDate = null ;
try
{
var cacheEntryDescriptor = httpCacheSession . openCacheEntry ( url , Components . interfaces . nsICache . ACCESS _READ , false ) ; // open for READ, in non-blocking mode
if ( cacheEntryDescriptor )
{
switch ( cacheEntryDescriptor . deviceID )
{
case "disk" :
sourceText = theBundle . getString ( "generalDiskCache" ) ;
break ;
case "memory" :
sourceText = theBundle . getString ( "generalMemoryCache" ) ;
break ;
default :
sourceText = cacheEntryDescriptor . deviceID ;
break ;
}
pageSize = cacheEntryDescriptor . dataSize ;
kbSize = pageSize / 1024 ;
sizeText = theBundle . getFormattedString ( "generalSize" , [ Math . round ( kbSize * 100 ) / 100 , pageSize ] ) ;
expirationText = formatDate ( cacheEntryDescriptor . expirationTime * 1000 , gStrings . notSet ) ;
}
}
catch ( ex )
{
try
{
cacheEntryDescriptor = ftpCacheSession . openCacheEntry ( url , Components . interfaces . nsICache . ACCESS _READ , false ) ; // open for READ, in non-blocking mode
if ( cacheEntryDescriptor )
{
switch ( cacheEntryDescriptor . deviceID )
{
case "disk" :
sourceText = theBundle . getString ( "generalDiskCache" ) ;
break ;
case "memory" :
sourceText = theBundle . getString ( "generalMemoryCache" ) ;
break ;
default :
sourceText = cacheEntryDescriptor . deviceID ;
break ;
}
pageSize = cacheEntryDescriptor . dataSize ;
kbSize = pageSize / 1024 ;
sizeText = theBundle . getFormattedString ( "generalSize" , [ Math . round ( kbSize * 100 ) / 100 , pageSize ] ) ;
expirationText = formatDate ( cacheEntryDescriptor . expirationTime * 1000 , gStrings . notSet ) ;
}
}
catch ( ex2 )
{
sourceText = theBundle . getString ( "generalNotCached" ) ;
}
}
document . getElementById ( "imagesourcetext" ) . value = sourceText ;
document . getElementById ( "imageexpirestext" ) . value = expirationText ;
document . getElementById ( "imagesizetext" ) . value = sizeText ;
var width = ( "width" in item && item . width ) || "" ;
var height = ( "height" in item && item . height ) || "" ;
document . getElementById ( "imagewidth" ) . value = theBundle . getFormattedString ( "mediaWidth" , [ width ] ) ;
document . getElementById ( "imageheight" ) . value = theBundle . getFormattedString ( "mediaHeight" , [ height ] ) ;
var imageContainer = document . getElementById ( "theimagecontainer" ) ;
var oldImage = document . getElementById ( "thepreviewimage" ) ;
var nn = item . nodeName . toLowerCase ( ) ;
var regex = new RegExp ( "^(https?|ftp|file|gopher)://" ) ;
var absoluteURL = getAbsoluteURL ( getSource ( item ) , item ) ;
var isProtocolAllowed = regex . test ( absoluteURL ) ;
var newImage = new Image ( ) ;
newImage . setAttribute ( "id" , "thepreviewimage" ) ;
if ( ( nn == "link" || nn == "input" || nn == "img" ) &&
isProtocolAllowed )
{
newImage . src = absoluteURL ;
if ( "width" in item && item . width )
newImage . width = item . width ;
if ( "height" in item && item . height )
newImage . height = item . height ;
}
else
{
// fallback image for protocols not allowed (e.g., data: or javascript:)
// or elements not [yet] handled (e.g., object, embed). XXX blank??
newImage . src = "resource:///res/loading-image.gif" ;
newImage . width = 40 ;
newImage . height = 40 ;
}
imageContainer . removeChild ( oldImage ) ;
imageContainer . appendChild ( newImage ) ;
}
//******** Other Misc Stuff
// Modified from the Links Panel v2.3, http://segment7.net/mozilla/links/links.html
// parse a node to extract the contents of the node
// linkNode doesn't really _have_ to be link
function getValueText ( linkNode )
{
var valueText = "" ;
var length = linkNode . childNodes . length ;
for ( var i = 0 ; i < length ; i ++ )
{
var childNode = linkNode . childNodes [ i ] ;
var nodeType = childNode . nodeType ;
if ( nodeType == Node . TEXT _NODE )
valueText += " " + childNode . nodeValue ;
else if ( nodeType == Node . ELEMENT _NODE )
{
if ( childNode . nodeName . toLowerCase ( ) == "img" )
valueText += " " + getAltText ( childNode ) ;
else
valueText += " " + getValueText ( childNode ) ;
}
}
return stripWS ( valueText ) ;
}
// Copied from the Links Panel v2.3, http://segment7.net/mozilla/links/links.html
// traverse the tree in search of an img or area element and grab its alt tag
function getAltText ( node )
{
var altText = "" ;
if ( node . alt )
return node . alt ;
var length = node . childNodes . length ;
for ( var i = 0 ; i < length ; i ++ )
if ( ( altText = getAltText ( node . childNodes [ i ] ) != undefined ) ) // stupid js warning...
return altText ;
return "" ;
}
// Copied from the Links Panel v2.3, http://segment7.net/mozilla/links/links.html
// strip leading and trailing whitespace, and replace multiple consecutive whitespace characters with a single space
function stripWS ( text )
{
var middleRE = /\s+/g ;
var endRE = /(^\s+)|(\s+$)/g ;
text = text . replace ( middleRE , " " ) ;
return text . replace ( endRE , "" ) ;
}
function formatDate ( datestr , unknown )
{
var date = new Date ( datestr ) ;
return ( date . valueOf ( ) ) ? dateService . FormatDateTime ( "" , dateService . dateFormatLong , dateService . timeFormatSeconds , date . getFullYear ( ) , date . getMonth ( ) + 1 , date . getDate ( ) , date . getHours ( ) , date . getMinutes ( ) , date . getSeconds ( ) ) : unknown ;
}
/ *
* Takes care of XMLBase and < base >
* url is the possibly relative url .
* node is the node where the url was given ( needed for XMLBase )
*
* This function is called in many places as a workaround for bug 72524
* Once bug 72522 is fixed this code should use the Node . baseURI attribute
*
* for node == null or url == "" , empty string is returned
*
* This is basically just copied from http : //lxr.mozilla.org/seamonkey/source/xpfe/browser/resources/content/metadata.js
* /
function getAbsoluteURL ( url , node )
{
if ( ! url || ! node )
return "" ;
var urlArr = new Array ( url ) ;
var doc = node . ownerDocument ;
if ( node . nodeType == Node . ATTRIBUTE _NODE )
node = node . ownerElement ;
while ( node && node . nodeType == Node . ELEMENT _NODE )
{
var att = node . getAttributeNS ( XMLNS , "base" ) ;
if ( att != "" )
urlArr . unshift ( att ) ;
node = node . parentNode ;
}
// Look for a <base>.
var baseTags = doc . getElementsByTagNameNS ( XHTMLNS , "base" ) ;
if ( baseTags && baseTags . length )
{
urlArr . unshift ( baseTags [ baseTags . length - 1 ] . getAttribute ( "href" ) ) ;
}
// resolve everything from bottom up, starting with document location
var ioService = Components . classes [ "@mozilla.org/network/io-service;1" ] . getService ( Components . interfaces . nsIIOService ) ;
var URL = ioService . newURI ( doc . location . href , null , null ) ;
for ( var i = 0 ; i < urlArr . length ; i ++ )
{
URL . spec = URL . resolve ( urlArr [ i ] ) ;
}
return URL . spec ;
}
function doCopy ( event )
{
if ( ! gClipboardHelper )
return ;
var elem = event . originalTarget ;
if ( elem && "treeBoxObject" in elem )
elem . treeBoxObject . view . performActionOnRow ( "copy" , elem . currentIndex ) ;
var text = elem . getAttribute ( "copybuffer" ) ;
if ( text )
gClipboardHelper . copyString ( text ) ;
}