Context menu updates

This commit is contained in:
law%netscape.com 1999-10-01 04:43:45 +00:00
parent fa4392cf29
commit b6d2de1cb0
12 changed files with 236 additions and 576 deletions

View File

@ -32,6 +32,7 @@
#include "nsIEventStateManager.h"
#include "nsDOMEvent.h"
#include "nsNeckoUtil.h"
// XXX suppress
@ -171,7 +172,6 @@ nsHTMLAnchorElement::CloneNode(PRBool aDeep, nsIDOMNode** aReturn)
NS_IMPL_STRING_ATTR(nsHTMLAnchorElement, AccessKey, accesskey)
NS_IMPL_STRING_ATTR(nsHTMLAnchorElement, Charset, charset)
NS_IMPL_STRING_ATTR(nsHTMLAnchorElement, Coords, coords)
NS_IMPL_STRING_ATTR(nsHTMLAnchorElement, Href, href)
NS_IMPL_STRING_ATTR(nsHTMLAnchorElement, Hreflang, hreflang)
NS_IMPL_STRING_ATTR(nsHTMLAnchorElement, Name, name)
NS_IMPL_STRING_ATTR(nsHTMLAnchorElement, Rel, rel)
@ -390,3 +390,39 @@ nsHTMLAnchorElement::HandleDOMEvent(nsIPresContext& aPresContext,
return ret;
}
NS_IMETHODIMP
nsHTMLAnchorElement::GetHref(nsString& aValue)
{
// Resolve url to an absolute url
nsresult rv = NS_OK;
nsAutoString relURLSpec;
nsIURI* baseURL = nsnull;
// Get base URL.
mInner.GetBaseURL(baseURL);
// Get href= attribute (relative URL).
mInner.GetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::href, relURLSpec);
// If there is no href=, then use base target.
if (relURLSpec.Length() == 0) {
mInner.GetBaseTarget(relURLSpec);
}
if (nsnull != baseURL) {
// Get absolute URL.
rv = NS_MakeAbsoluteURI(relURLSpec, baseURL, aValue);
}
else {
// Absolute URL is same as relative URL.
aValue = relURLSpec;
}
NS_IF_RELEASE(baseURL);
return rv;
}
NS_IMETHODIMP
nsHTMLAnchorElement::SetHref(const nsString& aValue)
{
return mInner.SetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::href, aValue, PR_TRUE);
}

View File

@ -462,8 +462,32 @@ nsHTMLImageElement::SetDocument(nsIDocument* aDocument,
NS_IMETHODIMP
nsHTMLImageElement::GetSrc(nsString& aSrc)
{
mInner.GetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::src, aSrc);
return NS_OK;
// Resolve url to an absolute url
nsresult rv = NS_OK;
nsAutoString relURLSpec;
nsIURI* baseURL = nsnull;
// Get base URL.
GetBaseURL(baseURL);
// Get href= attribute (relative URL).
mInner.GetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::src, relURLSpec);
// If there is no href=, then use base target.
if (relURLSpec.Length() == 0) {
GetBaseTarget(relURLSpec);
}
if (nsnull != baseURL) {
// Get absolute URL.
rv = NS_MakeAbsoluteURI(relURLSpec, baseURL, aSrc);
}
else {
// Absolute URL is same as relative URL.
aSrc = relURLSpec;
}
NS_IF_RELEASE(baseURL);
return rv;
}
NS_IMETHODIMP

View File

@ -32,6 +32,7 @@
#include "nsIEventStateManager.h"
#include "nsDOMEvent.h"
#include "nsNeckoUtil.h"
// XXX suppress
@ -171,7 +172,6 @@ nsHTMLAnchorElement::CloneNode(PRBool aDeep, nsIDOMNode** aReturn)
NS_IMPL_STRING_ATTR(nsHTMLAnchorElement, AccessKey, accesskey)
NS_IMPL_STRING_ATTR(nsHTMLAnchorElement, Charset, charset)
NS_IMPL_STRING_ATTR(nsHTMLAnchorElement, Coords, coords)
NS_IMPL_STRING_ATTR(nsHTMLAnchorElement, Href, href)
NS_IMPL_STRING_ATTR(nsHTMLAnchorElement, Hreflang, hreflang)
NS_IMPL_STRING_ATTR(nsHTMLAnchorElement, Name, name)
NS_IMPL_STRING_ATTR(nsHTMLAnchorElement, Rel, rel)
@ -390,3 +390,39 @@ nsHTMLAnchorElement::HandleDOMEvent(nsIPresContext& aPresContext,
return ret;
}
NS_IMETHODIMP
nsHTMLAnchorElement::GetHref(nsString& aValue)
{
// Resolve url to an absolute url
nsresult rv = NS_OK;
nsAutoString relURLSpec;
nsIURI* baseURL = nsnull;
// Get base URL.
mInner.GetBaseURL(baseURL);
// Get href= attribute (relative URL).
mInner.GetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::href, relURLSpec);
// If there is no href=, then use base target.
if (relURLSpec.Length() == 0) {
mInner.GetBaseTarget(relURLSpec);
}
if (nsnull != baseURL) {
// Get absolute URL.
rv = NS_MakeAbsoluteURI(relURLSpec, baseURL, aValue);
}
else {
// Absolute URL is same as relative URL.
aValue = relURLSpec;
}
NS_IF_RELEASE(baseURL);
return rv;
}
NS_IMETHODIMP
nsHTMLAnchorElement::SetHref(const nsString& aValue)
{
return mInner.SetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::href, aValue, PR_TRUE);
}

View File

@ -462,8 +462,32 @@ nsHTMLImageElement::SetDocument(nsIDocument* aDocument,
NS_IMETHODIMP
nsHTMLImageElement::GetSrc(nsString& aSrc)
{
mInner.GetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::src, aSrc);
return NS_OK;
// Resolve url to an absolute url
nsresult rv = NS_OK;
nsAutoString relURLSpec;
nsIURI* baseURL = nsnull;
// Get base URL.
GetBaseURL(baseURL);
// Get href= attribute (relative URL).
mInner.GetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::src, relURLSpec);
// If there is no href=, then use base target.
if (relURLSpec.Length() == 0) {
GetBaseTarget(relURLSpec);
}
if (nsnull != baseURL) {
// Get absolute URL.
rv = NS_MakeAbsoluteURI(relURLSpec, baseURL, aSrc);
}
else {
// Absolute URL is same as relative URL.
aSrc = relURLSpec;
}
NS_IF_RELEASE(baseURL);
return rv;
}
NS_IMETHODIMP

View File

@ -971,9 +971,16 @@ nsMenuFrame::BuildAcceleratorText(nsString& aAccelString)
void
nsMenuFrame::Execute()
{
// Temporarily disable rollup events on this menu. This is
// to suppress this menu getting removed in the case where
// the oncommand handler opens a dialog, etc.
if ( nsMenuFrame::mDismissalListener ) {
nsMenuFrame::mDismissalListener->EnableListener(PR_FALSE);
}
// Get our own content node and hold on to it to keep it from going away.
nsCOMPtr<nsIContent> content = dont_QueryInterface(mContent);
// First hide all of the open menus.
if (mMenuParent)
mMenuParent->HideChain();
@ -992,6 +999,11 @@ nsMenuFrame::Execute()
// Now properly close them all up.
if (doc && mMenuParent)
mMenuParent->DismissChain();
// Re-enable rollup events on this menu.
if ( nsMenuFrame::mDismissalListener ) {
nsMenuFrame::mDismissalListener->EnableListener(PR_TRUE);
}
}
PRBool

View File

@ -701,6 +701,21 @@ function OpenSearch(tabName, searchStr)
return Components.classes[ progid ].createInstance( iid );
}
function createInstanceById( cid, iidName ) {
var iid = eval( "Components.interfaces." + iidName );
return Components.classesByID[ cid ].createInstance( iid );
}
function getService( progid, iidName ) {
var iid = eval( "Components.interfaces." + iidName );
return Components.classes[ progid ].getService( iid );
}
function getServiceById( cid, iidName ) {
var iid = eval( "Components.interfaces." + iidName );
return Components.classesByID[ cid ].getService( iid );
}
function openNewWindowWith( url ) {
var newWin = window.openDialog( "chrome://navigator/content/navigator.xul", "_blank", "chrome,all,dialog=no", url );
@ -952,11 +967,15 @@ function OpenSearch(tabName, searchStr)
if ( status ) {
var text = status.getAttribute("value");
if ( text == "" ) {
//dump( "Setting default status text\n" );
text = defaultStatus;
}
var statusText = document.getElementById("statusText");
if ( statusText ) {
//dump( "Setting status text: " + text + "\n" );
statusText.setAttribute( "value", text );
} else {
//dump( "Missing statusText when setting status text: " + text + "\n" );
}
} else {
dump("Can't find status broadcaster!\n");
@ -1148,278 +1167,17 @@ function FitToScreen()
}
}
// Set given attribute of specified context-menu item. If the
// value is null, then it removes the attribute (which works
// nicely for the disabled attribute).
function setContextMenuItemAttr( id, attr, val ) {
var elem = document.getElementById( id );
if ( elem ) {
if ( val == null ) {
// null indicates attr should be removed.
elem.removeAttribute( attr );
} else {
// Set attr=val.
elem.setAttribute( attr, val );
}
// Dumps all properties of anObject.
function dumpObject( anObject, prefix ) {
if ( prefix == null ) {
prefix = anObject;
}
}
// Set context menu attribute according to like attribute of another node
// (such as a broadcaster).
function setContextMenuItemAttrFromNode( item_id, attr, other_id ) {
var elem = document.getElementById( other_id );
if ( elem && elem.getAttribute( attr ) == "true" ) {
setContextMenuItemAttr( item_id, attr, "true" );
} else {
setContextMenuItemAttr( item_id, attr, null );
for ( prop in anObject ) {
dump( prefix + "." + prop + " = " + anObject[prop] + "\n" );
}
}
// Return "true" if we're not on a link, null otherwise (seems odd, but it gives
// us the proper value to which to set a disabled attribute to).
function isNotOnLink( event ) {
// Not implemented so all link-based options are disabled.
return "true";
}
// Returns "true" if we're not in a frame, null otherwise (see above).
function isNotInFrame( event ) {
// Not implemented so all frame-based options are disabled.
return "true";
}
// Returns "true" if we're not on an image, null otherwise (see above).
function isNotOnImage( event ) {
// Not implemented so all image-based options are disabled.
return "true";
}
// Returns "true" if we're not on a background image, null otherwise (see above).
function isNotOnBGImage( event ) {
// Not implemented so all background-image-based options are disabled.
return "true";
}
// Returns "true" if there's no text selected, null otherwise (see above).
function isNoTextSelected( event ) {
// Not implemented so all text-selected-based options are disabled.
return "true";
}
// Takes JS expression and dumps "expr="+expr+"\n"
function dumpExpr( expr ) {
dump( expr+"="+eval(expr)+"\n" );
}
// Function to display contextual info.
function dumpContext() {
dumpExpr( " contextTarget.element" );
dumpExpr( "contextTarget.element.tagName" );
dumpExpr( " contextTarget.onImage" );
dumpExpr( " contextTarget.imageSrc" );
dumpExpr( " contextTarget.onLink" );
dumpExpr( " contextTarget.linkHref" );
dumpExpr( " contextTarget.inFrame" );
dumpExpr( " contextTarget.frameHref" );
dumpExpr( " contextTarget.hasBGImage" );
dumpExpr( " contextTarget.bgImageSrc" );
}
// Remember what was clicked on and gather info about it.
var contextTarget;
function BrowserSetContextTarget( node ) {
// Initialize contextual info.
contextTarget = new Object;
contextTarget.onImage = false;
contextTarget.onLink = false;
contextTarget.inFrame = false;
contextTarget.hasBGImage = false;
// Remember the element that was clicked.
contextTarget.element = node;
// See if the user clicked on an image.
if ( contextTarget.element.nodeType == 1
&&
contextTarget.element.tagName.toUpperCase() == "IMG" ) {
// Record that.
contextTarget.onImage = true;
contextTarget.imageSrc = contextTarget.element.getAttribute( "SRC" );
}
// See if the user clicked in a frame.
if ( contextTarget.element.ownerDocument != window.content.document ) {
contextTarget.inFrame = true;
contextTarget.frameHref = contextTarget.element.ownerDocument.location.href;
}
// Bubble out, looking for link.
var elem = contextTarget.element;
while ( elem ) {
// Test for element types of interest.
if ( elem.nodeType == 1 && elem.tagName.toUpperCase() == "A" ) {
// Clicked on a link.
contextTarget.onLink = true;
contextTarget.linkHref = elem.getAttribute( "HREF" );
break;
}
elem = elem.parentNode;
}
dumpContext();
}
// Set various context menu attributes based on the state of the world.
function BrowserSetupContextMenu( menu, event ) {
// Get context.
BrowserSetContextTarget(document.popupNode);
//-------------------------------------------------------------------------
var needSep = false;
// Remove open/edit link if not applicable.
if ( !contextTarget.onLink ) {
menu.removeChild( document.getElementById( "context-openlink" ) );
menu.removeChild( document.getElementById( "context-editlink" ) );
} else {
needSep = true;
}
// Remove open frame if not applicable.
if ( !contextTarget.inFrame ) {
menu.removeChild( document.getElementById( "context-openframe" ) );
} else {
needSep = true;
}
if ( !needSep ) {
// Remove separator.
menu.removeChild( document.getElementById( "context-sep-open" ) );
}
//-------------------------------------------------------------------------
// Back determined by canGoBack broadcaster.
setContextMenuItemAttrFromNode( "context-back", "disabled", "canGoBack" );
// Forward determined by canGoForward broadcaster.
setContextMenuItemAttrFromNode( "context-forward", "disabled", "canGoForward" );
// Reload is always OK.
// Stop determined by canStop broadcaster.
setContextMenuItemAttrFromNode( "context-stop", "disabled", "canStop" );
//-------------------------------------------------------------------------
// View source is always OK.
// View frame source depends on whether we're in a frame.
if ( !contextTarget.inFrame ) {
menu.removeChild( document.getElementById( "context-viewframesource" ) );
}
// View Info don't work no way no how.
menu.removeChild( document.getElementById( "context-viewinfo" ) );
// View Frame Info isn't working, either.
menu.removeChild( document.getElementById( "context-viewframeinfo" ) );
// View Image depends on whether an image was clicked on.
if ( !contextTarget.onImage ) {
menu.removeChild( document.getElementById( "context-viewimage" ) );
}
//-------------------------------------------------------------------------
// Add bookmark always OK.
// Send Page not working yet.
menu.removeChild( document.getElementById( "context-sendpage" ) );
//-------------------------------------------------------------------------
// Save page is always OK.
// Save frame as depends on whether we're in a frame.
if ( !contextTarget.inFrame ) {
menu.removeChild( document.getElementById( "context-saveframe" ) );
}
// Save link depends on whether we're in a link.
if ( !contextTarget.onLink ) {
menu.removeChild( document.getElementById( "context-savelink" ) );
}
// Save background image depends on whether there is one.
if ( !contextTarget.hasBGImage ) {
menu.removeChild( document.getElementById( "context-savebgimage" ) );
}
// Save image depends on whether there is one.
if ( !contextTarget.onImage ) {
menu.removeChild( document.getElementById( "context-saveimage" ) );
}
//-------------------------------------------------------------------------
// Select All is always OK.
// Copy depends on whether there is selected text.
setContextMenuItemAttr( "context-copy", "disabled", isNoTextSelected() );
// Copy link location depends on whether we're on a link.
if ( !contextTarget.onLink ) {
menu.removeChild( document.getElementById( "context-copylink" ) );
}
// Copy image location depends on whether we're on an image.
if ( !contextTarget.onImage ) {
menu.removeChild( document.getElementById( "context-copyimage" ) );
}
}
// Temporary workaround for DOM api not yet implemented.
function cloneNode( item ) {
// Create another element like the one we're cloning.
var node = document.createElement( item.tagName );
// Copy attributes from argument item to the new one.
var attrs = item.attributes;
for ( var i = 0; i < attrs.length; i++ ) {
var attr = attrs.item( i );
node.setAttribute( attr.nodeName, attr.nodeValue );
}
// Voila!
return node;
}
// "create" the context menu by cloning the template.
function BrowserCreateContextMenu( menu, event ) {
var template = document.getElementById( "context-template" );
var items = template.childNodes;
for ( var i = 0; i < items.length; i++ ) {
// Replicate item.
//var item = items.item(i).cloneNode( false );
// cloneNode not implemented, fake it.
var item = cloneNode( items.item(i) );
// Change id.
item.setAttribute( "id", item.getAttribute( "id" ).replace( "template-", "context-" ) );
// Add it to popup menu.
menu.appendChild( item );
}
// Tweak the menu.
BrowserSetupContextMenu( menu, event );
}
// Remove all the children which we added at oncreate.
function BrowserDestroyContextMenu( menu ) {
var items = menu.childNodes;
for ( var i = 0; i < items.length; i++ ) {
menu.removeChild( items.item(i) );
}
}

View File

@ -48,6 +48,7 @@ Contributor(s): ______________________________________. -->
<html:script language="javascript" src="chrome://global/content/strres.js" />
<html:script language="javascript" src="navigator.js" />
<html:script language="javascript" src="nsContextMenu.js" />
<html:script language="javascript" src="tooltip.js" />
<!-- broadcasters are appended from the overlay -->
@ -81,15 +82,18 @@ Contributor(s): ______________________________________. -->
</popupset>
<!-- Context menu -->
<html:script language="javascript">
// Global variable that holds the nsContextMenu instance.
var contextMenu = null;
</html:script>
<popupset>
<!-- This is the skeleton context menu. It is populated and emptied
dynamically, from the template (see below) via the oncreate/ondestroy
handlers.
-->
<popup id="context"
oncreate="BrowserCreateContextMenu(this,event)"
ondestroy="BrowserDestroyContextMenu(this)">
</popup>
oncreate="contextMenu = new nsContextMenu( this );"
ondestroy="contextMenu.onDestroy(); contextMenu = null;"/>
<!-- This is the context menu template used to populate the actual
content menu on demand. It holds everything and is whittled down
@ -100,15 +104,15 @@ Contributor(s): ______________________________________. -->
<menuitem id="template-openlink"
value="&openLinkCmd.label;"
accesskey=""
oncommand="BrowserOpenLink();"/>
oncommand="contextMenu.openLink();"/>
<menuitem id="template-editlink"
value="&editLinkCmd.label;"
accesskey=""
oncommand="BrowserEditLink();"/>
oncommand="contextMenu.editLink();"/>
<menuitem id="template-openframe"
value="&openFrameCmd.label;"
accesskey=""
oncommand="BrowserOpenFrame();"/>
oncommand="contextMenu.openFrame();"/>
<menuseparator id="context-sep-open"/>
<!-- Navigation ============================== -->
<menuitem id="template-back"
@ -136,19 +140,19 @@ Contributor(s): ______________________________________. -->
<menuitem id="template-viewframesource"
value="&viewFrameSourceCmd.label;"
accesskey=""
oncommand="BrowserViewFrameSource();"/>
oncommand="contextMenu.viewFrameSource();"/>
<menuitem id="template-viewinfo"
value="&viewPageInfoCmd.label;"
accesskey=""
oncommand="BrowserViewInfo();"/>
oncommand="contextMenu.viewInfo();"/>
<menuitem id="template-viewframeinfo"
value="&viewFrameInfoCmd.label;"
accesskey=""
oncommand="BrowserViewFrameInfo();"/>
oncommand="contextMenu.viewFrameInfo();"/>
<menuitem id="template-viewimage"
value="&viewImageCmd.label;"
accesskey=""
oncommand="BrowserViewImage();"/>
oncommand="contextMenu.viewImage();"/>
<menuseparator/>
<!-- Misc ==================================== -->
<menuitem id="template-bookmarkpage"
@ -165,23 +169,23 @@ Contributor(s): ______________________________________. -->
<menuitem id="template-savepage"
value="&savePageCmd.label;"
accesskey="&savePageCmd.accesskey;"
oncommand="BrowserSavePage();"/>
oncommand="contextMenu.savePage();"/>
<menuitem id="template-saveframe"
value="&saveFrameCmd.label;"
accesskey="&saveFrameCmd.accesskey;"
oncommand="BrowserSaveFrame();"/>
oncommand="contextMenu.saveFrame();"/>
<menuitem id="template-savelink"
value="&saveLinkCmd.label;"
accesskey="&saveLinkCmd.accesskey;"
oncommand="BrowserSaveLink();"/>
oncommand="contextMenu.saveLink();"/>
<menuitem id="template-saveimage"
value="&saveImageCmd.label;"
accesskey="&saveImageCmd.accesskey;"
oncommand="BrowserSaveImage();"/>
oncommand="contextMenu.saveImage();"/>
<menuitem id="template-savebgimage"
value="&saveBGImageCmd.label;"
accesskey="&saveBGImageCmd.accesskey;"
oncommand="BrowserSaveBGImage();"/>
oncommand="contextMenu.saveBGImage();"/>
<menuseparator/>
<!-- Clipboard =============================== -->
<menuitem id="template-selectall"
@ -195,11 +199,11 @@ Contributor(s): ______________________________________. -->
<menuitem id="template-copylink"
value="&copyLinkCmd.label;"
accesskey="&copyLinkCmd.accesskey;"
oncommand="BrowserCopyLink();"/>
oncommand="contextMenu.copyLink();"/>
<menuitem id="template-copyimage"
value="&copyImageCmd.label;"
accesskey="&copyImageCmd.accesskey;"
oncommand="BrowserCopyImage();"/>
oncommand="contextMenu.copyImage();"/>
</popup>
</popupset>

View File

@ -23,6 +23,7 @@ VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
EXPORT_RESOURCE_CONTENT = \
$(srcdir)/nsContextMenu.js \
$(srcdir)/tooltip.js \
$(srcdir)/contentframe.js \
$(srcdir)/openLocation.js \

View File

@ -9,4 +9,5 @@ openLocation.xul
viewSource.xul
NetSupportConfirmYN.xul
NetSupportConfirmCheckYN.xul
tooltip.js
tooltip.js
nsContextMenu.js

View File

@ -34,6 +34,7 @@ install::
$(MAKE_INSTALL) NetSupportConfirmYN.xul $(DISTBROWSWER)
$(MAKE_INSTALL) NetSupportConfirmCheckYN.xul $(DISTBROWSWER)
$(MAKE_INSTALL) tooltip.js $(DISTBROWSWER)
$(MAKE_INSTALL) nsContextMenu.js $(DISTBROWSWER)
clobber::
@ -49,3 +50,4 @@ clobber::
rm -f $(DISTBROWSER)\NetSupportConfirmYN.xul
rm -f $(DISTBROWSER)\NetSupportConfirmCheckYN.xul
rm -f $(DISTBROWSER)\tooltip.js
rm -f $(DISTBROWSER)\nsContextMenu.js

View File

@ -701,6 +701,21 @@ function OpenSearch(tabName, searchStr)
return Components.classes[ progid ].createInstance( iid );
}
function createInstanceById( cid, iidName ) {
var iid = eval( "Components.interfaces." + iidName );
return Components.classesByID[ cid ].createInstance( iid );
}
function getService( progid, iidName ) {
var iid = eval( "Components.interfaces." + iidName );
return Components.classes[ progid ].getService( iid );
}
function getServiceById( cid, iidName ) {
var iid = eval( "Components.interfaces." + iidName );
return Components.classesByID[ cid ].getService( iid );
}
function openNewWindowWith( url ) {
var newWin = window.openDialog( "chrome://navigator/content/navigator.xul", "_blank", "chrome,all,dialog=no", url );
@ -952,11 +967,15 @@ function OpenSearch(tabName, searchStr)
if ( status ) {
var text = status.getAttribute("value");
if ( text == "" ) {
//dump( "Setting default status text\n" );
text = defaultStatus;
}
var statusText = document.getElementById("statusText");
if ( statusText ) {
//dump( "Setting status text: " + text + "\n" );
statusText.setAttribute( "value", text );
} else {
//dump( "Missing statusText when setting status text: " + text + "\n" );
}
} else {
dump("Can't find status broadcaster!\n");
@ -1148,278 +1167,17 @@ function FitToScreen()
}
}
// Set given attribute of specified context-menu item. If the
// value is null, then it removes the attribute (which works
// nicely for the disabled attribute).
function setContextMenuItemAttr( id, attr, val ) {
var elem = document.getElementById( id );
if ( elem ) {
if ( val == null ) {
// null indicates attr should be removed.
elem.removeAttribute( attr );
} else {
// Set attr=val.
elem.setAttribute( attr, val );
}
// Dumps all properties of anObject.
function dumpObject( anObject, prefix ) {
if ( prefix == null ) {
prefix = anObject;
}
}
// Set context menu attribute according to like attribute of another node
// (such as a broadcaster).
function setContextMenuItemAttrFromNode( item_id, attr, other_id ) {
var elem = document.getElementById( other_id );
if ( elem && elem.getAttribute( attr ) == "true" ) {
setContextMenuItemAttr( item_id, attr, "true" );
} else {
setContextMenuItemAttr( item_id, attr, null );
for ( prop in anObject ) {
dump( prefix + "." + prop + " = " + anObject[prop] + "\n" );
}
}
// Return "true" if we're not on a link, null otherwise (seems odd, but it gives
// us the proper value to which to set a disabled attribute to).
function isNotOnLink( event ) {
// Not implemented so all link-based options are disabled.
return "true";
}
// Returns "true" if we're not in a frame, null otherwise (see above).
function isNotInFrame( event ) {
// Not implemented so all frame-based options are disabled.
return "true";
}
// Returns "true" if we're not on an image, null otherwise (see above).
function isNotOnImage( event ) {
// Not implemented so all image-based options are disabled.
return "true";
}
// Returns "true" if we're not on a background image, null otherwise (see above).
function isNotOnBGImage( event ) {
// Not implemented so all background-image-based options are disabled.
return "true";
}
// Returns "true" if there's no text selected, null otherwise (see above).
function isNoTextSelected( event ) {
// Not implemented so all text-selected-based options are disabled.
return "true";
}
// Takes JS expression and dumps "expr="+expr+"\n"
function dumpExpr( expr ) {
dump( expr+"="+eval(expr)+"\n" );
}
// Function to display contextual info.
function dumpContext() {
dumpExpr( " contextTarget.element" );
dumpExpr( "contextTarget.element.tagName" );
dumpExpr( " contextTarget.onImage" );
dumpExpr( " contextTarget.imageSrc" );
dumpExpr( " contextTarget.onLink" );
dumpExpr( " contextTarget.linkHref" );
dumpExpr( " contextTarget.inFrame" );
dumpExpr( " contextTarget.frameHref" );
dumpExpr( " contextTarget.hasBGImage" );
dumpExpr( " contextTarget.bgImageSrc" );
}
// Remember what was clicked on and gather info about it.
var contextTarget;
function BrowserSetContextTarget( node ) {
// Initialize contextual info.
contextTarget = new Object;
contextTarget.onImage = false;
contextTarget.onLink = false;
contextTarget.inFrame = false;
contextTarget.hasBGImage = false;
// Remember the element that was clicked.
contextTarget.element = node;
// See if the user clicked on an image.
if ( contextTarget.element.nodeType == 1
&&
contextTarget.element.tagName.toUpperCase() == "IMG" ) {
// Record that.
contextTarget.onImage = true;
contextTarget.imageSrc = contextTarget.element.getAttribute( "SRC" );
}
// See if the user clicked in a frame.
if ( contextTarget.element.ownerDocument != window.content.document ) {
contextTarget.inFrame = true;
contextTarget.frameHref = contextTarget.element.ownerDocument.location.href;
}
// Bubble out, looking for link.
var elem = contextTarget.element;
while ( elem ) {
// Test for element types of interest.
if ( elem.nodeType == 1 && elem.tagName.toUpperCase() == "A" ) {
// Clicked on a link.
contextTarget.onLink = true;
contextTarget.linkHref = elem.getAttribute( "HREF" );
break;
}
elem = elem.parentNode;
}
dumpContext();
}
// Set various context menu attributes based on the state of the world.
function BrowserSetupContextMenu( menu, event ) {
// Get context.
BrowserSetContextTarget(document.popupNode);
//-------------------------------------------------------------------------
var needSep = false;
// Remove open/edit link if not applicable.
if ( !contextTarget.onLink ) {
menu.removeChild( document.getElementById( "context-openlink" ) );
menu.removeChild( document.getElementById( "context-editlink" ) );
} else {
needSep = true;
}
// Remove open frame if not applicable.
if ( !contextTarget.inFrame ) {
menu.removeChild( document.getElementById( "context-openframe" ) );
} else {
needSep = true;
}
if ( !needSep ) {
// Remove separator.
menu.removeChild( document.getElementById( "context-sep-open" ) );
}
//-------------------------------------------------------------------------
// Back determined by canGoBack broadcaster.
setContextMenuItemAttrFromNode( "context-back", "disabled", "canGoBack" );
// Forward determined by canGoForward broadcaster.
setContextMenuItemAttrFromNode( "context-forward", "disabled", "canGoForward" );
// Reload is always OK.
// Stop determined by canStop broadcaster.
setContextMenuItemAttrFromNode( "context-stop", "disabled", "canStop" );
//-------------------------------------------------------------------------
// View source is always OK.
// View frame source depends on whether we're in a frame.
if ( !contextTarget.inFrame ) {
menu.removeChild( document.getElementById( "context-viewframesource" ) );
}
// View Info don't work no way no how.
menu.removeChild( document.getElementById( "context-viewinfo" ) );
// View Frame Info isn't working, either.
menu.removeChild( document.getElementById( "context-viewframeinfo" ) );
// View Image depends on whether an image was clicked on.
if ( !contextTarget.onImage ) {
menu.removeChild( document.getElementById( "context-viewimage" ) );
}
//-------------------------------------------------------------------------
// Add bookmark always OK.
// Send Page not working yet.
menu.removeChild( document.getElementById( "context-sendpage" ) );
//-------------------------------------------------------------------------
// Save page is always OK.
// Save frame as depends on whether we're in a frame.
if ( !contextTarget.inFrame ) {
menu.removeChild( document.getElementById( "context-saveframe" ) );
}
// Save link depends on whether we're in a link.
if ( !contextTarget.onLink ) {
menu.removeChild( document.getElementById( "context-savelink" ) );
}
// Save background image depends on whether there is one.
if ( !contextTarget.hasBGImage ) {
menu.removeChild( document.getElementById( "context-savebgimage" ) );
}
// Save image depends on whether there is one.
if ( !contextTarget.onImage ) {
menu.removeChild( document.getElementById( "context-saveimage" ) );
}
//-------------------------------------------------------------------------
// Select All is always OK.
// Copy depends on whether there is selected text.
setContextMenuItemAttr( "context-copy", "disabled", isNoTextSelected() );
// Copy link location depends on whether we're on a link.
if ( !contextTarget.onLink ) {
menu.removeChild( document.getElementById( "context-copylink" ) );
}
// Copy image location depends on whether we're on an image.
if ( !contextTarget.onImage ) {
menu.removeChild( document.getElementById( "context-copyimage" ) );
}
}
// Temporary workaround for DOM api not yet implemented.
function cloneNode( item ) {
// Create another element like the one we're cloning.
var node = document.createElement( item.tagName );
// Copy attributes from argument item to the new one.
var attrs = item.attributes;
for ( var i = 0; i < attrs.length; i++ ) {
var attr = attrs.item( i );
node.setAttribute( attr.nodeName, attr.nodeValue );
}
// Voila!
return node;
}
// "create" the context menu by cloning the template.
function BrowserCreateContextMenu( menu, event ) {
var template = document.getElementById( "context-template" );
var items = template.childNodes;
for ( var i = 0; i < items.length; i++ ) {
// Replicate item.
//var item = items.item(i).cloneNode( false );
// cloneNode not implemented, fake it.
var item = cloneNode( items.item(i) );
// Change id.
item.setAttribute( "id", item.getAttribute( "id" ).replace( "template-", "context-" ) );
// Add it to popup menu.
menu.appendChild( item );
}
// Tweak the menu.
BrowserSetupContextMenu( menu, event );
}
// Remove all the children which we added at oncreate.
function BrowserDestroyContextMenu( menu ) {
var items = menu.childNodes;
for ( var i = 0; i < items.length; i++ ) {
menu.removeChild( items.item(i) );
}
}

View File

@ -48,6 +48,7 @@ Contributor(s): ______________________________________. -->
<html:script language="javascript" src="chrome://global/content/strres.js" />
<html:script language="javascript" src="navigator.js" />
<html:script language="javascript" src="nsContextMenu.js" />
<html:script language="javascript" src="tooltip.js" />
<!-- broadcasters are appended from the overlay -->
@ -81,15 +82,18 @@ Contributor(s): ______________________________________. -->
</popupset>
<!-- Context menu -->
<html:script language="javascript">
// Global variable that holds the nsContextMenu instance.
var contextMenu = null;
</html:script>
<popupset>
<!-- This is the skeleton context menu. It is populated and emptied
dynamically, from the template (see below) via the oncreate/ondestroy
handlers.
-->
<popup id="context"
oncreate="BrowserCreateContextMenu(this,event)"
ondestroy="BrowserDestroyContextMenu(this)">
</popup>
oncreate="contextMenu = new nsContextMenu( this );"
ondestroy="contextMenu.onDestroy(); contextMenu = null;"/>
<!-- This is the context menu template used to populate the actual
content menu on demand. It holds everything and is whittled down
@ -100,15 +104,15 @@ Contributor(s): ______________________________________. -->
<menuitem id="template-openlink"
value="&openLinkCmd.label;"
accesskey=""
oncommand="BrowserOpenLink();"/>
oncommand="contextMenu.openLink();"/>
<menuitem id="template-editlink"
value="&editLinkCmd.label;"
accesskey=""
oncommand="BrowserEditLink();"/>
oncommand="contextMenu.editLink();"/>
<menuitem id="template-openframe"
value="&openFrameCmd.label;"
accesskey=""
oncommand="BrowserOpenFrame();"/>
oncommand="contextMenu.openFrame();"/>
<menuseparator id="context-sep-open"/>
<!-- Navigation ============================== -->
<menuitem id="template-back"
@ -136,19 +140,19 @@ Contributor(s): ______________________________________. -->
<menuitem id="template-viewframesource"
value="&viewFrameSourceCmd.label;"
accesskey=""
oncommand="BrowserViewFrameSource();"/>
oncommand="contextMenu.viewFrameSource();"/>
<menuitem id="template-viewinfo"
value="&viewPageInfoCmd.label;"
accesskey=""
oncommand="BrowserViewInfo();"/>
oncommand="contextMenu.viewInfo();"/>
<menuitem id="template-viewframeinfo"
value="&viewFrameInfoCmd.label;"
accesskey=""
oncommand="BrowserViewFrameInfo();"/>
oncommand="contextMenu.viewFrameInfo();"/>
<menuitem id="template-viewimage"
value="&viewImageCmd.label;"
accesskey=""
oncommand="BrowserViewImage();"/>
oncommand="contextMenu.viewImage();"/>
<menuseparator/>
<!-- Misc ==================================== -->
<menuitem id="template-bookmarkpage"
@ -165,23 +169,23 @@ Contributor(s): ______________________________________. -->
<menuitem id="template-savepage"
value="&savePageCmd.label;"
accesskey="&savePageCmd.accesskey;"
oncommand="BrowserSavePage();"/>
oncommand="contextMenu.savePage();"/>
<menuitem id="template-saveframe"
value="&saveFrameCmd.label;"
accesskey="&saveFrameCmd.accesskey;"
oncommand="BrowserSaveFrame();"/>
oncommand="contextMenu.saveFrame();"/>
<menuitem id="template-savelink"
value="&saveLinkCmd.label;"
accesskey="&saveLinkCmd.accesskey;"
oncommand="BrowserSaveLink();"/>
oncommand="contextMenu.saveLink();"/>
<menuitem id="template-saveimage"
value="&saveImageCmd.label;"
accesskey="&saveImageCmd.accesskey;"
oncommand="BrowserSaveImage();"/>
oncommand="contextMenu.saveImage();"/>
<menuitem id="template-savebgimage"
value="&saveBGImageCmd.label;"
accesskey="&saveBGImageCmd.accesskey;"
oncommand="BrowserSaveBGImage();"/>
oncommand="contextMenu.saveBGImage();"/>
<menuseparator/>
<!-- Clipboard =============================== -->
<menuitem id="template-selectall"
@ -195,11 +199,11 @@ Contributor(s): ______________________________________. -->
<menuitem id="template-copylink"
value="&copyLinkCmd.label;"
accesskey="&copyLinkCmd.accesskey;"
oncommand="BrowserCopyLink();"/>
oncommand="contextMenu.copyLink();"/>
<menuitem id="template-copyimage"
value="&copyImageCmd.label;"
accesskey="&copyImageCmd.accesskey;"
oncommand="BrowserCopyImage();"/>
oncommand="contextMenu.copyImage();"/>
</popup>
</popupset>