зеркало из https://github.com/mozilla/pjs.git
Fix 59707: extract navigator's context menu and allow it to be used elsewhere in the app (and to help in embedding). r=jag a=alecf
This commit is contained in:
Родитель
2c4258b8a3
Коммит
c577348464
|
@ -0,0 +1,103 @@
|
|||
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Contributors:
|
||||
*
|
||||
* Alec Flett <alecf@netscape.com>
|
||||
* Ben Goodger <ben@netscape.com>
|
||||
* Mike Pinkerton <pinkerton@netscape.com>
|
||||
* Blake Ross <blakeross@telocity.com>
|
||||
*/
|
||||
|
||||
var pref = null;
|
||||
pref = Components.classes["@mozilla.org/preferences;1"];
|
||||
pref = pref.getService();
|
||||
pref = pref.QueryInterface(Components.interfaces.nsIPref);
|
||||
|
||||
// Called whenever the user clicks in the content area,
|
||||
// except when left-clicking on links (special case)
|
||||
// should always return true for click to go through
|
||||
function contentAreaClick(event)
|
||||
{
|
||||
var target = event.originalTarget;
|
||||
var linkNode;
|
||||
switch (target.localName.toLowerCase()) {
|
||||
case "a":
|
||||
linkNode = event.target;
|
||||
break;
|
||||
case "area":
|
||||
if (event.target.href)
|
||||
linkNode = event.target;
|
||||
break;
|
||||
default:
|
||||
linkNode = findParentNode(target, "a");
|
||||
break;
|
||||
}
|
||||
if (linkNode) {
|
||||
handleLinkClick(event, linkNode.href);
|
||||
return true;
|
||||
}
|
||||
if (pref && event.button == 2 &&
|
||||
!findParentNode(target, "scrollbar") &&
|
||||
pref.GetBoolPref("middlemouse.paste")) {
|
||||
middleMousePaste(event);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function handleLinkClick(event, href)
|
||||
{
|
||||
switch (event.button) {
|
||||
case 1: // if left button clicked
|
||||
if (event.metaKey || event.ctrlKey) { // and meta or ctrl are down
|
||||
openNewWindowWith(href); // open link in new window
|
||||
event.preventBubble();
|
||||
return true;
|
||||
}
|
||||
if (event.shiftKey) { // if shift is down
|
||||
savePage(href); // save the link
|
||||
return true;
|
||||
}
|
||||
if (event.altKey) // if alt is down
|
||||
return true; // do nothing
|
||||
return false;
|
||||
case 2: // if middle button clicked
|
||||
if (pref && pref.GetBoolPref("middlemouse.openNewWindow")) { // and the pref is on
|
||||
openNewWindowWith(href); // open link in new window
|
||||
event.preventBubble();
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function middleMousePaste(event)
|
||||
{
|
||||
var url = readFromClipboard();
|
||||
//dump ("Loading URL on clipboard: '" + url + "'; length = " + url.length + "\n");
|
||||
if (url) {
|
||||
var urlBar = document.getElementById("urlbar");
|
||||
urlBar.value = url;
|
||||
BrowserLoadURL();
|
||||
event.preventBubble();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
|
@ -0,0 +1,182 @@
|
|||
<?xml version="1.0"?>
|
||||
<!-- 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 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.
|
||||
-
|
||||
- Contributor(s):
|
||||
- Blake Ross <blakeross@telocity.com>
|
||||
-->
|
||||
<!DOCTYPE window SYSTEM "chrome://communicator/locale/contentAreaCommands.dtd" >
|
||||
<overlay id="contentAreaContextOverlay"
|
||||
xmlns:html="http://www.w3.org/1999/xhtml"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
|
||||
<!-- Context menu -->
|
||||
<script language="javascript">
|
||||
// Global variable that holds the nsContextMenu instance.
|
||||
var contextMenu = null;
|
||||
</script>
|
||||
<script type="text/javascript" src="chrome://communicator/content/nsContextMenu.js"/>
|
||||
<script type="text/javascript" src="chrome://communicator/content/contentAreaUtils.js"/>
|
||||
|
||||
<popupset id="contentAreaContextSet">
|
||||
<!-- This is the context menu for the content-area of the navigator
|
||||
window. It contains each and every possible menu choice. The
|
||||
appropriate items are hidden/shown upon display, based on what
|
||||
the user has clicked-on.
|
||||
-->
|
||||
<popup id="contentAreaContextMenu"
|
||||
oncreate="contextMenu = new nsContextMenu( this ); return contextMenu.shouldDisplay;"
|
||||
ondestroy="contextMenu.onDestroy(); contextMenu = null;">
|
||||
<!-- Open ==================================== -->
|
||||
<menuitem id="context-openlink"
|
||||
value="&openLinkCmd.label;"
|
||||
accesskey=""
|
||||
oncommand="contextMenu.openLink();"/>
|
||||
<!-- XXX - DEPENDENT ON PRESENCE OF EDITOR!! - XXX -->
|
||||
<menuitem id="context-editlink"
|
||||
value="&editLinkCmd.label;"
|
||||
accesskey=""
|
||||
oncommand="contextMenu.editLink();"/>
|
||||
<menuitem id="context-openframe"
|
||||
value="&openFrameCmd.label;"
|
||||
accesskey=""
|
||||
oncommand="contextMenu.openFrame();"/>
|
||||
<menuitem id="context-showonlythisframe"
|
||||
value="&showOnlyThisFrameCmd.label;"
|
||||
accesskey="&showOnlyThisFrameCmd.accesskey;"
|
||||
oncommand="contextMenu.showOnlyThisFrame();"/>
|
||||
<menuseparator id="context-sep-open"/>
|
||||
<!-- Navigation ============================== -->
|
||||
<menuitem id="context-back"
|
||||
value="&goBackCmd.label;"
|
||||
accesskey="&goBackCmd.accesskey;"
|
||||
oncommand="BrowserBack()"/>
|
||||
<menuitem id="context-forward"
|
||||
value="&goForwardCmd.label;"
|
||||
accesskey="&goForwardCmd.accesskey;"
|
||||
oncommand="BrowserForward()"/>
|
||||
<menuitem id="context-reload"
|
||||
value="&reloadCmd.label;"
|
||||
accesskey="&reloadCmd.accesskey;"
|
||||
oncommand="BrowserReallyReload(event);"/>
|
||||
<menuitem id="context-reload-frame"
|
||||
value="&reloadFrameCmd.label;"
|
||||
accesskey="&reloadFrameCmd.accesskey;"
|
||||
oncommand="contextMenu.reloadFrame();"/>
|
||||
<menuitem id="context-stop"
|
||||
value="&stopCmd.label;"
|
||||
accesskey=""
|
||||
oncommand="BrowserStop();"/>
|
||||
<menuseparator/>
|
||||
<!-- View ==================================== -->
|
||||
<menuitem id="context-viewsource"
|
||||
value="&viewPageSourceCmd.label;"
|
||||
accesskey=""
|
||||
oncommand="BrowserViewSource();"/>
|
||||
<menuitem id="context-viewframesource"
|
||||
value="&viewFrameSourceCmd.label;"
|
||||
accesskey=""
|
||||
oncommand="contextMenu.viewFrameSource();"/>
|
||||
<menuitem id="context-viewinfo"
|
||||
value="&viewPageInfoCmd.label;"
|
||||
accesskey=""
|
||||
oncommand="contextMenu.viewInfo();"/>
|
||||
<menuitem id="context-viewframeinfo"
|
||||
value="&viewFrameInfoCmd.label;"
|
||||
accesskey=""
|
||||
oncommand="contextMenu.viewFrameInfo();"/>
|
||||
<menuitem id="context-viewimage"
|
||||
value="&viewImageCmd.label;"
|
||||
accesskey=""
|
||||
oncommand="contextMenu.viewImage();"/>
|
||||
<menuitem id="context-blockimage"
|
||||
value="&blockImageCmd.label;"
|
||||
accesskey=""
|
||||
oncommand="contextMenu.blockImage();"/>
|
||||
<menuseparator id="context-sep-view"/>
|
||||
<!-- Misc ==================================== -->
|
||||
<menuitem id="context-bookmarkpage"
|
||||
value="&bookmarkPageCmd.label;"
|
||||
accesskey="&bookmarkPageCmd.accesskey;"
|
||||
oncommand="BrowserAddBookmark( window._content.location.href,
|
||||
window._content.document.title )"/>
|
||||
<menuitem id="context-bookmarklink"
|
||||
value="&bookmarkLinkCmd.label;"
|
||||
accesskey="&bookmarkLinkCmd.accesskey;"
|
||||
oncommand="BrowserAddBookmark( contextMenu.linkURL(),
|
||||
contextMenu.linkText() )"/>
|
||||
<menuseparator/>
|
||||
<!-- Save ==================================== -->
|
||||
<menuitem id="context-savepage"
|
||||
value="&savePageCmd.label;"
|
||||
accesskey="&savePageCmd.accesskey;"
|
||||
oncommand="contextMenu.savePage();"/>
|
||||
<menuitem id="context-saveframe"
|
||||
value="&saveFrameCmd.label;"
|
||||
accesskey="&saveFrameCmd.accesskey;"
|
||||
oncommand="contextMenu.saveFrame();"/>
|
||||
<menuitem id="context-savelink"
|
||||
value="&saveLinkCmd.label;"
|
||||
accesskey="&saveLinkCmd.accesskey;"
|
||||
oncommand="contextMenu.saveLink();"/>
|
||||
<menuitem id="context-saveimage"
|
||||
value="&saveImageCmd.label;"
|
||||
accesskey="&saveImageCmd.accesskey;"
|
||||
oncommand="contextMenu.saveImage();"/>
|
||||
<menuitem id="context-savebgimage"
|
||||
value="&saveBGImageCmd.label;"
|
||||
accesskey="&saveBGImageCmd.accesskey;"
|
||||
oncommand="contextMenu.saveBGImage();"/>
|
||||
<menuseparator id="context-sep-save"/>
|
||||
<!-- Clipboard =============================== -->
|
||||
<menuitem id="context-selectall"
|
||||
value="&selectAllCmd.label;"
|
||||
accesskey="&selectAllCmd.accesskey;"
|
||||
observes="cmd_selectAll"/>
|
||||
<menuitem id="context-cut"
|
||||
value="&cutCmd.label;"
|
||||
accesskey="&cutCmd.accesskey;"
|
||||
observes="cmd_cut"/>
|
||||
<menuitem id="context-copy"
|
||||
value="©Cmd.label;"
|
||||
accesskey="©Cmd.accesskey;"
|
||||
observes="cmd_copy"/>
|
||||
<menuitem id="context-paste"
|
||||
value="&pasteCmd.label;"
|
||||
accesskey="&pasteCmd.accesskey;"
|
||||
observes="cmd_paste"/>
|
||||
<menuitem id="context-capture"
|
||||
value="&captureCmd.label;"
|
||||
accesskey=""
|
||||
oncommand="contextMenu.capture();"/>
|
||||
<menuitem id="context-prefill"
|
||||
value="&prefillCmd.label;"
|
||||
accesskey=""
|
||||
oncommand="contextMenu.prefill();"/>
|
||||
<menuitem id="context-copylink"
|
||||
value="©LinkCmd.label;"
|
||||
accesskey="©LinkCmd.accesskey;"
|
||||
oncommand="contextMenu.copyLink();"/>
|
||||
<menuitem id="context-copyimage"
|
||||
value="©ImageCmd.label;"
|
||||
accesskey="©ImageCmd.accesskey;"
|
||||
oncommand="contextMenu.copyImage();"/>
|
||||
</popup>
|
||||
</popupset>
|
||||
</overlay>
|
|
@ -19,130 +19,31 @@
|
|||
*
|
||||
* Contributors:
|
||||
*
|
||||
* Alec Flett <alecf@netscape.com>
|
||||
* Ben Goodger <ben@netscape.com>
|
||||
* Mike Pinkerton <pinkerton@netscape.com>
|
||||
* Blake Ross <blakeross@telocity.com>
|
||||
*/
|
||||
|
||||
var pref = null;
|
||||
pref = Components.classes["@mozilla.org/preferences;1"];
|
||||
pref = pref.getService();
|
||||
pref = pref.QueryInterface(Components.interfaces.nsIPref);
|
||||
|
||||
function findParentNode(node, parentNode)
|
||||
{
|
||||
while (node) {
|
||||
var nodeName = node.localName;
|
||||
if (!nodeName)
|
||||
return null;
|
||||
nodeName = nodeName.toLowerCase();
|
||||
if (nodeName == "body" || nodeName == "html" ||
|
||||
nodeName == "#document") {
|
||||
return null;
|
||||
}
|
||||
if (nodeName == parentNode)
|
||||
return node;
|
||||
node = node.parentNode;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// Called whenever the user clicks in the content area,
|
||||
// except when left-clicking on links (special case)
|
||||
// should always return true for click to go through
|
||||
function contentAreaClick(event)
|
||||
{
|
||||
var target = event.originalTarget;
|
||||
var linkNode;
|
||||
switch (target.localName.toLowerCase()) {
|
||||
case "a":
|
||||
linkNode = event.target;
|
||||
break;
|
||||
case "area":
|
||||
if (event.target.href)
|
||||
linkNode = event.target;
|
||||
break;
|
||||
default:
|
||||
linkNode = findParentNode(target, "a");
|
||||
break;
|
||||
}
|
||||
if (linkNode) {
|
||||
handleLinkClick(event, linkNode.href);
|
||||
return true;
|
||||
}
|
||||
if (pref && event.button == 2 &&
|
||||
!findParentNode(target, "scrollbar") &&
|
||||
pref.GetBoolPref("middlemouse.paste")) {
|
||||
middleMousePaste(event);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function handleLinkClick(event, href)
|
||||
{
|
||||
switch (event.button) {
|
||||
case 1: // if left button clicked
|
||||
if (event.metaKey || event.ctrlKey) { // and meta or ctrl are down
|
||||
openNewWindowWith(href); // open link in new window
|
||||
event.preventBubble();
|
||||
return true;
|
||||
}
|
||||
if (event.shiftKey) { // if shift is down
|
||||
savePage(href); // save the link
|
||||
return true;
|
||||
}
|
||||
if (event.altKey) // if alt is down
|
||||
return true; // do nothing
|
||||
return false;
|
||||
case 2: // if middle button clicked
|
||||
if (pref && pref.GetBoolPref("middlemouse.openNewWindow")) { // and the pref is on
|
||||
openNewWindowWith(href); // open link in new window
|
||||
event.preventBubble();
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function middleMousePaste(event)
|
||||
{
|
||||
var url = readFromClipboard();
|
||||
//dump ("Loading URL on clipboard: '" + url + "'; length = " + url.length + "\n");
|
||||
if (url) {
|
||||
var urlBar = document.getElementById("urlbar");
|
||||
urlBar.value = url;
|
||||
BrowserLoadURL();
|
||||
event.preventBubble();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function openNewWindowWith( url ) {
|
||||
var newWin;
|
||||
var wintype = document.firstChild.getAttribute('windowtype');
|
||||
function openNewWindowWith( url ) {
|
||||
var newWin;
|
||||
var wintype = document.firstChild.getAttribute('windowtype');
|
||||
|
||||
// if and only if the current window is a browser window and it has a document with a character
|
||||
// set, then extract the current charset menu setting from the current document and use it to
|
||||
// initialize the new browser window...
|
||||
if (window && (wintype == "navigator:browser") &&
|
||||
window._content && window._content.document) {
|
||||
var DocCharset = window._content.document.characterSet;
|
||||
charsetArg = "charset="+DocCharset;
|
||||
dump("*** Current document charset: " + DocCharset + "\n");
|
||||
// if and only if the current window is a browser window and it has a document with a character
|
||||
// set, then extract the current charset menu setting from the current document and use it to
|
||||
// initialize the new browser window...
|
||||
if (window && (wintype == "navigator:browser") &&
|
||||
window._content && window._content.document) {
|
||||
var DocCharset = window._content.document.characterSet;
|
||||
charsetArg = "charset="+DocCharset;
|
||||
dump("*** Current document charset: " + DocCharset + "\n");
|
||||
|
||||
//we should "inherit" the charset menu setting in a new window
|
||||
newWin = window.openDialog( getBrowserURL(), "_blank", "chrome,all,dialog=no", url, charsetArg );
|
||||
}
|
||||
else { // forget about the charset information.
|
||||
newWin = window.openDialog( getBrowserURL(), "_blank", "chrome,all,dialog=no", url );
|
||||
}
|
||||
//we should "inherit" the charset menu setting in a new window
|
||||
newWin = window.openDialog( getBrowserURL(), "_blank", "chrome,all,dialog=no", url, charsetArg );
|
||||
}
|
||||
else { // forget about the charset information.
|
||||
newWin = window.openDialog( getBrowserURL(), "_blank", "chrome,all,dialog=no", url );
|
||||
}
|
||||
|
||||
// Fix new window.
|
||||
newWin.saveFileAndPos = true;
|
||||
}
|
||||
// Fix new window.
|
||||
newWin.saveFileAndPos = true;
|
||||
}
|
||||
|
||||
function savePage(url)
|
||||
{
|
||||
|
@ -164,4 +65,27 @@
|
|||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
function editPage(url)
|
||||
{
|
||||
window.openDialog( "chrome://editor/content", "_blank", "chrome,all,dialog=no", url );
|
||||
}
|
||||
|
||||
function findParentNode(node, parentNode)
|
||||
{
|
||||
while (node) {
|
||||
var nodeName = node.localName;
|
||||
if (!nodeName)
|
||||
return null;
|
||||
nodeName = nodeName.toLowerCase();
|
||||
if (nodeName == "body" || nodeName == "html" ||
|
||||
nodeName == "#document") {
|
||||
return null;
|
||||
}
|
||||
if (nodeName == parentNode)
|
||||
return node;
|
||||
node = node.parentNode;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,832 @@
|
|||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/*
|
||||
* 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 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 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* William A. ("PowerGUI") Law <law@netscape.com>
|
||||
* Blake Ross <blakeross@telocity.com>
|
||||
*/
|
||||
|
||||
/*------------------------------ nsContextMenu ---------------------------------
|
||||
| This JavaScript "class" is used to implement the browser's content-area |
|
||||
| context menu. |
|
||||
| |
|
||||
| For usage, see references to this class in navigator.xul. |
|
||||
| |
|
||||
| Currently, this code is relatively useless for any other purpose. In the |
|
||||
| longer term, this code will be restructured to make it more reusable. |
|
||||
------------------------------------------------------------------------------*/
|
||||
function nsContextMenu( xulMenu ) {
|
||||
this.target = null;
|
||||
this.menu = null;
|
||||
this.onTextInput = false;
|
||||
this.onImage = false;
|
||||
this.onLink = false;
|
||||
this.onSaveableLink = false;
|
||||
this.link = false;
|
||||
this.inFrame = false;
|
||||
this.hasBGImage = false;
|
||||
this.inDirList = false;
|
||||
this.shouldDisplay = true;
|
||||
this.disableCapture = false;
|
||||
|
||||
// Initialize new menu.
|
||||
this.initMenu( xulMenu );
|
||||
}
|
||||
|
||||
// Prototype for nsContextMenu "class."
|
||||
nsContextMenu.prototype = {
|
||||
// onDestroy is a no-op at this point.
|
||||
onDestroy : function () {
|
||||
},
|
||||
// Initialize context menu.
|
||||
initMenu : function ( popup, event ) {
|
||||
// Save menu.
|
||||
this.menu = popup;
|
||||
|
||||
// Get contextual info.
|
||||
this.setTarget( document.popupNode );
|
||||
|
||||
// Initialize (disable/remove) menu items.
|
||||
this.initItems();
|
||||
},
|
||||
initItems : function () {
|
||||
this.initOpenItems();
|
||||
this.initNavigationItems();
|
||||
this.initViewItems();
|
||||
this.initMiscItems();
|
||||
this.initSaveItems();
|
||||
this.initClipboardItems();
|
||||
},
|
||||
initOpenItems : function () {
|
||||
// Remove open/edit link if not applicable.
|
||||
this.showItem( "context-openlink", this.onSaveableLink || ( this.inDirList && this.onLink ) );
|
||||
this.showItem( "context-editlink", this.onSaveableLink && !this.inDirList );
|
||||
|
||||
// Remove open frame if not applicable.
|
||||
this.showItem( "context-openframe", this.inFrame );
|
||||
this.showItem( "context-showonlythisframe", this.inFrame );
|
||||
|
||||
// Remove separator after open items if neither link nor frame.
|
||||
this.showItem( "context-sep-open", this.onSaveableLink || ( this.inDirList && this.onLink ) || this.inFrame );
|
||||
},
|
||||
initNavigationItems : function () {
|
||||
// Back determined by canGoBack broadcaster.
|
||||
this.setItemAttrFromNode( "context-back", "disabled", "canGoBack" );
|
||||
|
||||
// Forward determined by canGoForward broadcaster.
|
||||
this.setItemAttrFromNode( "context-forward", "disabled", "canGoForward" );
|
||||
|
||||
// Reload is OK if not on a frame; vice-versa for reload-frame.
|
||||
this.showItem( "context-reload", !this.inFrame );
|
||||
this.showItem( "context-reload-frame", this.inFrame );
|
||||
|
||||
// XXX: Stop is determined in navigator.js; the canStop broadcaster is broken
|
||||
//this.setItemAttrFromNode( "context-stop", "disabled", "canStop" );
|
||||
},
|
||||
initSaveItems : function () {
|
||||
// Save page is always OK, unless in directory listing.
|
||||
this.showItem( "context-savepage", !this.inDirList );
|
||||
|
||||
// Save frame as depends on whether we're in a frame.
|
||||
this.showItem( "context-saveframe", this.inFrame );
|
||||
|
||||
// Save link depends on whether we're in a link.
|
||||
this.showItem( "context-savelink", this.onSaveableLink );
|
||||
|
||||
// Save background image depends on whether there is one.
|
||||
this.showItem( "context-savebgimage", this.hasBGImage );
|
||||
|
||||
// Save image depends on whether there is one.
|
||||
this.showItem( "context-saveimage", this.onImage );
|
||||
|
||||
// Remove separator if none of these were shown.
|
||||
var showSep = !this.inDirList || this.inFrame || this.onSaveableLink || this.hasBGImage || this.onImage;
|
||||
this.showItem( "context-sep-save", showSep );
|
||||
},
|
||||
initViewItems : function () {
|
||||
// View source is always OK, unless in directory listing.
|
||||
this.showItem( "context-viewsource", !this.inDirList );
|
||||
|
||||
// View frame source depends on whether we're in a frame.
|
||||
this.showItem( "context-viewframesource", this.inFrame );
|
||||
|
||||
// View Info don't work no way no how.
|
||||
this.showItem( "context-viewinfo", false );
|
||||
|
||||
// View Frame Info isn't working, either.
|
||||
this.showItem( "context-viewframeinfo", false );
|
||||
|
||||
// View Image depends on whether an image was clicked on.
|
||||
this.showItem( "context-viewimage", this.onImage );
|
||||
|
||||
// Block image depends on whether an image was clicked on, and,
|
||||
// whether the user pref is enabled.
|
||||
this.showItem( "context-blockimage", this.onImage && this.isBlockingImages() );
|
||||
|
||||
// Capture depends on whether a form is being displayed.
|
||||
this.showItem( "context-capture", this.okToCapture() );
|
||||
this.setItemAttr( "context-capture", "disabled", this.disableCapture);
|
||||
|
||||
// Prefill depends on whether a form is being displayed.
|
||||
this.showItem( "context-prefill", this.okToPrefill() );
|
||||
|
||||
// Remove separator if all items are removed.
|
||||
this.showItem( "context-sep-view", !this.inDirList || this.inFrame || this.onImage );
|
||||
},
|
||||
initMiscItems : function () {
|
||||
// Use "Bookmark This Link" if on a link.
|
||||
this.showItem( "context-bookmarkpage", !this.onLink );
|
||||
this.showItem( "context-bookmarklink", this.onLink );
|
||||
|
||||
// Send Page not working yet.
|
||||
this.showItem( "context-sendpage", false );
|
||||
},
|
||||
initClipboardItems : function () {
|
||||
// Select All is always OK, unless in directory listing.
|
||||
this.showItem( "context-selectall", !this.inDirList );
|
||||
|
||||
// Copy depends on whether there is selected text.
|
||||
// Enabling this context menu item is now done through the global
|
||||
// command updating system
|
||||
// this.setItemAttr( "context-copy", "disabled", this.isNoTextSelected() );
|
||||
|
||||
goUpdateGlobalEditMenuItems();
|
||||
|
||||
// Items for text areas
|
||||
this.showItem( "context-cut", this.onTextInput );
|
||||
this.showItem( "context-paste", this.onTextInput );
|
||||
|
||||
// Copy link location depends on whether we're on a link.
|
||||
this.showItem( "context-copylink", this.onLink );
|
||||
|
||||
// Copy image location depends on whether we're on an image.
|
||||
this.showItem( "context-copyimage", this.onImage );
|
||||
},
|
||||
// Set various context menu attributes based on the state of the world.
|
||||
setTarget : function ( node ) {
|
||||
// Initialize contextual info.
|
||||
this.onImage = false;
|
||||
this.onTextInput = false;
|
||||
this.imageURL = "";
|
||||
this.onLink = false;
|
||||
this.inFrame = false;
|
||||
this.hasBGImage = false;
|
||||
|
||||
// Remember the node that was clicked.
|
||||
this.target = node;
|
||||
|
||||
// See if the user clicked on an image.
|
||||
if ( this.target.nodeType == 1 ) {
|
||||
if ( this.target.tagName.toUpperCase() == "IMG" ) {
|
||||
this.onImage = true;
|
||||
this.imageURL = this.target.src;
|
||||
// Look for image map.
|
||||
var mapName = this.target.getAttribute( "usemap" );
|
||||
if ( mapName ) {
|
||||
// Find map.
|
||||
var map = this.target.ownerDocument.getElementById( mapName.substr(1) );
|
||||
if ( map ) {
|
||||
// Search child <area>s for a match.
|
||||
var areas = map.childNodes;
|
||||
//XXX Client side image maps are too hard for now!
|
||||
dump( "Client side image maps not supported yet, sorry!\n" );
|
||||
areas.length = 0;
|
||||
for ( var i = 0; i < areas.length && !this.onLink; i++ ) {
|
||||
var area = areas[i];
|
||||
if ( area.nodeType == 1
|
||||
&&
|
||||
area.tagName.toUpperCase() == "AREA" ) {
|
||||
// Get type (rect/circle/polygon/default).
|
||||
var type = area.getAttribute( "type" );
|
||||
var coords = this.parseCoords( area );
|
||||
switch ( type.toUpperCase() ) {
|
||||
case "RECT":
|
||||
case "RECTANGLE":
|
||||
break;
|
||||
case "CIRC":
|
||||
case "CIRCLE":
|
||||
break;
|
||||
case "POLY":
|
||||
case "POLYGON":
|
||||
break;
|
||||
case "DEFAULT":
|
||||
// Default matches entire image.
|
||||
this.onLink = true;
|
||||
this.link = area;
|
||||
this.onSaveableLink = this.isLinkSaveable( this.link );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if ( this.target.tagName.toUpperCase() == "OBJECT"
|
||||
&&
|
||||
// See if object tag is for an image.
|
||||
this.objectIsImage( this.target ) ) {
|
||||
// This is an image.
|
||||
this.onImage = true;
|
||||
// URL must be constructed.
|
||||
this.imageURL = this.objectImageURL( this.target );
|
||||
} else if ( this.target.tagName.toUpperCase() == "INPUT") {
|
||||
if(this.target.getAttribute( "type" ).toUpperCase() == "IMAGE") {
|
||||
this.onImage = true;
|
||||
// Convert src attribute to absolute URL.
|
||||
this.imageURL = this.makeURLAbsolute( this.target.ownerDocument,
|
||||
this.target.src );
|
||||
} else /* if (this.target.getAttribute( "type" ).toUpperCase() == "TEXT") */ {
|
||||
this.onTextInput = this.isTargetATextField(this.target);
|
||||
}
|
||||
} else if ( this.target.tagName.toUpperCase() == "TEXTAREA" ) {
|
||||
this.onTextInput = true;
|
||||
} else if ( this.target.getAttribute( "background" ) ) {
|
||||
this.onImage = true;
|
||||
// Convert background attribute to absolute URL.
|
||||
this.imageURL = this.makeURLAbsolute( this.target.ownerDocument,
|
||||
this.target.getAttribute( "background" ) );
|
||||
} else if ( window._content.HTTPIndex == "[xpconnect wrapped nsIHTTPIndex]"
|
||||
&&
|
||||
typeof window._content.HTTPIndex == "object"
|
||||
&&
|
||||
!window._content.HTTPIndex.constructor ) {
|
||||
// The above test is a roundabout way of determining whether
|
||||
// the content area contains chrome://global/content/directory/directory.xul.
|
||||
this.inDirList = true;
|
||||
// Bubble outward till we get to an element with id= attribute
|
||||
// (which should be the href).
|
||||
var root = this.target;
|
||||
while ( root && !this.link ) {
|
||||
if ( root.getAttribute( "id" ) ) {
|
||||
if ( root.tagName == "tree" ) {
|
||||
// Hit root of tree; must have clicked in empty space;
|
||||
// thus, no link.
|
||||
break;
|
||||
}
|
||||
// Build pseudo link object so link-related functions work.
|
||||
this.onLink = true;
|
||||
this.link = { href : root.getAttribute( "id" ) };
|
||||
// If element is a directory, then you can't save it.
|
||||
if ( root.getAttribute( "container" ) == "true" ) {
|
||||
this.onSaveableLink = false;
|
||||
} else {
|
||||
this.onSaveableLink = true;
|
||||
}
|
||||
} else {
|
||||
root = root.parentNode;
|
||||
}
|
||||
}
|
||||
} else if ( this.target.parentNode.tagName == "scrollbar"
|
||||
||
|
||||
this.target.parentNode.tagName == "thumb"
|
||||
||
|
||||
this.target.parentNode.tagName == "xul:slider") {
|
||||
this.shouldDisplay = false;
|
||||
} else {
|
||||
try {
|
||||
var cssAttr = this.target.style.getPropertyValue( "list-style-image" ) ||
|
||||
this.target.style.getPropertyValue( "list-style" ) ||
|
||||
this.target.style.getPropertyValue( "background-image" ) ||
|
||||
this.target.style.getPropertyValue( "background" );
|
||||
if ( cssAttr ) {
|
||||
this.onImage = true;
|
||||
var url = cssAttr.toLowerCase().replace(/url\("*(.+)"*\)/, "$1");
|
||||
// Convert attribute to absolute URL.
|
||||
this.imageURL = this.makeURLAbsolute( this.target.ownerDocument, url );
|
||||
}
|
||||
} catch ( exception ) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// See if the user clicked in a frame.
|
||||
if ( this.target.ownerDocument != window._content.document ) {
|
||||
this.inFrame = true;
|
||||
}
|
||||
|
||||
// Bubble up looking for an input or textarea
|
||||
var elem = this.target;
|
||||
while ( elem && !this.onTextInput ) {
|
||||
// Test for element types of interest.
|
||||
if ( elem.nodeType == 1 ) {
|
||||
// Clicked on a link.
|
||||
this.onTextInput = this.isTargetATextField(elem);
|
||||
}
|
||||
elem = elem.parentNode;
|
||||
}
|
||||
|
||||
// Bubble out, looking for link.
|
||||
elem = this.target;
|
||||
while ( elem && !this.onLink ) {
|
||||
// Test for element types of interest.
|
||||
if ( elem.nodeType == 1 &&
|
||||
( elem.tagName.toUpperCase() == "A"
|
||||
||
|
||||
elem.tagName.toUpperCase() == "AREA"
|
||||
||
|
||||
elem.getAttributeNS("http://www.w3.org/1999/xlink","type") == "simple")) {
|
||||
// Clicked on a link.
|
||||
this.onLink = true;
|
||||
// Remember corresponding element.
|
||||
this.link = elem;
|
||||
// Remember if it is saveable.
|
||||
this.onSaveableLink = this.isLinkSaveable( this.link );
|
||||
}
|
||||
elem = elem.parentNode;
|
||||
}
|
||||
},
|
||||
// Returns true iff clicked on link is saveable.
|
||||
isLinkSaveable : function ( link ) {
|
||||
// Test for missing protocol property.
|
||||
if ( !link.protocol ) {
|
||||
// We must resort to testing the URL string :-(.
|
||||
var protocol;
|
||||
if (link.href) {
|
||||
protocol = link.href.substr( 0, 11 );
|
||||
} else {
|
||||
protocol = link.getAttributeNS("http://www.w3.org/1999/xlink","href");
|
||||
if (protocol) {
|
||||
protocol = protocol.substr( 0, 11 );
|
||||
}
|
||||
}
|
||||
return protocol.toLowerCase() != "javascript:";
|
||||
} else {
|
||||
// Presume all but javascript: urls are saveable.
|
||||
return link.protocol.toLowerCase() != "javascript:";
|
||||
}
|
||||
},
|
||||
// Open linked-to URL in a new window.
|
||||
openLink : function () {
|
||||
// Determine linked-to URL.
|
||||
openNewWindowWith( this.linkURL() );
|
||||
},
|
||||
// Edit linked-to URL in a new window.
|
||||
editLink : function () {
|
||||
editPage( this.linkURL() );
|
||||
},
|
||||
// Reload clicked-in frame.
|
||||
reloadFrame : function () {
|
||||
this.target.ownerDocument.location.reload();
|
||||
},
|
||||
// Open clicked-in frame in its own window.
|
||||
openFrame : function () {
|
||||
openNewWindowWith( this.target.ownerDocument.location.href );
|
||||
},
|
||||
// Open clicked-in frame in the same window
|
||||
showOnlyThisFrame : function () {
|
||||
window._content.location.href = this.target.ownerDocument.location.href;
|
||||
},
|
||||
// Open new "view source" window with the frame's URL.
|
||||
viewFrameSource : function () {
|
||||
window.openDialog( "chrome://navigator/content/viewSource.xul",
|
||||
"_blank",
|
||||
"scrollbars,resizable,chrome,dialog=no",
|
||||
this.target.ownerDocument.location.href);
|
||||
},
|
||||
viewInfo : function () {
|
||||
dump( "nsContextMenu.viewInfo not implemented yet\n" );
|
||||
},
|
||||
viewFrameInfo : function () {
|
||||
dump( "nsContextMenu.viewFrameInfo not implemented yet\n" );
|
||||
},
|
||||
// Open new window with the URL of the image.
|
||||
viewImage : function () {
|
||||
openNewWindowWith( this.imageURL );
|
||||
},
|
||||
// Save URL of clicked-on frame.
|
||||
saveFrame : function () {
|
||||
this.savePage( this.target.ownerDocument.location.href, true );
|
||||
},
|
||||
// Save URL of clicked-on link.
|
||||
saveLink : function () {
|
||||
this.savePage( this.linkURL(), false );
|
||||
},
|
||||
// Save URL of clicked-on image.
|
||||
saveImage : function () {
|
||||
this.savePage( this.imageURL, true );
|
||||
},
|
||||
// Save URL of background image.
|
||||
saveBGImage : function () {
|
||||
this.savePage( this.bgImageURL(), true );
|
||||
},
|
||||
// Generate link URL and put it on clibboard.
|
||||
copyLink : function () {
|
||||
this.copyToClipboard( this.linkURL() );
|
||||
},
|
||||
// Generate image URL and put it on the clipboard.
|
||||
copyImage : function () {
|
||||
this.copyToClipboard( this.imageURL );
|
||||
},
|
||||
|
||||
// Capture the values that are filled in on the form being displayed.
|
||||
capture : function () {
|
||||
var walletService = Components.classes["@mozilla.org/wallet/wallet-service;1"].getService(Components.interfaces.nsIWalletService);
|
||||
|
||||
walletService.WALLET_RequestToCapture(window._content);
|
||||
},
|
||||
// Prefill the form being displayed.
|
||||
prefill : function () {
|
||||
walletPreview(window._content);
|
||||
},
|
||||
|
||||
// Determine if "Save Form Data" is to appear in the menu.
|
||||
okToCapture: function () {
|
||||
this.disableCapture = false;
|
||||
var rv = false;
|
||||
if (!window._content.document) {
|
||||
return false;
|
||||
}
|
||||
// test for a form with at least one text element that has a value
|
||||
var formsArray = this.target.ownerDocument.forms;
|
||||
if (!formsArray) {
|
||||
return false;
|
||||
}
|
||||
var form;
|
||||
for (form=0; form<formsArray.length; form++) {
|
||||
var elementsArray = formsArray[form].elements;
|
||||
var element;
|
||||
for (element=0; element<elementsArray.length; element++) {
|
||||
var type = elementsArray[element].type;
|
||||
if (type=="" || type=="text") {
|
||||
// we have a form with at least one text element
|
||||
var value = elementsArray[element].value;
|
||||
rv = true;
|
||||
if (value != "") {
|
||||
// at least one text element has a value, thus capture is to appear in menu
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// if we got here, then there was no text element with a value
|
||||
if (rv) {
|
||||
// if we got here, then we had a form with at least one text element
|
||||
// in that case capture is to appear in menu but will be disabled
|
||||
this.disableCapture = true;
|
||||
}
|
||||
return rv;
|
||||
},
|
||||
|
||||
// Determine if "Prefill Form" is to appear in the menu.
|
||||
okToPrefill: function () {
|
||||
if (!window._content.document) {
|
||||
return false;
|
||||
}
|
||||
var formsArray = this.target.ownerDocument.forms;
|
||||
if (!formsArray) {
|
||||
return false;
|
||||
}
|
||||
var form;
|
||||
for (form=0; form<formsArray.length; form++) {
|
||||
var elementsArray = formsArray[form].elements;
|
||||
var element;
|
||||
for (element=0; element<elementsArray.length; element++) {
|
||||
var type = elementsArray[element].type;
|
||||
var value = elementsArray[element].value;
|
||||
if (type=="" || type=="text" || type=="select-one") {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
// Determine if "Block Image" is to appear in the menu.
|
||||
// Return true if "imageBlocker.enabled" pref is set and image is not already blocked.
|
||||
isBlockingImages: function () {
|
||||
/* determine if "imageBlocker.enabled" pref is set */
|
||||
var pref = this.getService( '@mozilla.org/preferences;1', 'nsIPref' );
|
||||
var result = false;
|
||||
try {
|
||||
result = pref.GetBoolPref( "imageblocker.enabled" );
|
||||
} catch(e) {
|
||||
}
|
||||
if (!result) {
|
||||
/* pref is not set so return false */
|
||||
return false;
|
||||
}
|
||||
|
||||
/* determine if image is already being blocked */
|
||||
var cookieViewer = this.createInstance
|
||||
("@mozilla.org/cookieviewer/cookieviewer-world;1", "nsICookieViewer");
|
||||
var list = cookieViewer.GetPermissionValue(1);
|
||||
var permissionList = list.split(list[0]);
|
||||
for(var i = 1; i < permissionList.length; i+=2) {
|
||||
permStr = permissionList[i+1];
|
||||
var type = permStr.substring(0,1);
|
||||
if (type == "-") {
|
||||
/* some host is being blocked, need to find out if it's our image's host */
|
||||
var host = permStr.substring(1,permStr.length);
|
||||
if (this.imageURL.search(host) != -1) {
|
||||
/* it's our image's host that's being blocked */
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* image is not already being blocked, so "Block Image" can appear on the menu */
|
||||
return true;
|
||||
},
|
||||
// Block image from loading in the future.
|
||||
blockImage : function () {
|
||||
var cookieViewer = this.createInstance( "@mozilla.org/cookieviewer/cookieviewer-world;1",
|
||||
"nsICookieViewer" );
|
||||
cookieViewer.BlockImage(this.imageURL);
|
||||
},
|
||||
|
||||
///////////////
|
||||
// Utilities //
|
||||
///////////////
|
||||
|
||||
// Create instance of component given contractId and iid (as string).
|
||||
createInstance : function ( contractId, iidName ) {
|
||||
var iid = Components.interfaces[ iidName ];
|
||||
return Components.classes[ contractId ].createInstance( iid );
|
||||
},
|
||||
// Get service given contractId and iid (as string).
|
||||
getService : function ( contractId, iidName ) {
|
||||
var iid = Components.interfaces[ iidName ];
|
||||
return Components.classes[ contractId ].getService( iid );
|
||||
},
|
||||
// Show/hide one item (specified via name or the item element itself).
|
||||
showItem : function ( itemOrId, show ) {
|
||||
var item = null;
|
||||
if ( itemOrId.constructor == String ) {
|
||||
// Argument specifies item id.
|
||||
item = document.getElementById( itemOrId );
|
||||
} else {
|
||||
// Argument is the item itself.
|
||||
item = itemOrId;
|
||||
}
|
||||
if ( item ) {
|
||||
var styleIn = item.getAttribute( "style" );
|
||||
var styleOut = styleIn;
|
||||
if ( show ) {
|
||||
// Remove style="display:none;".
|
||||
styleOut = styleOut.replace( "display:none;", "" );
|
||||
|
||||
} else {
|
||||
// Set style="display:none;".
|
||||
if ( styleOut.indexOf( "display:none;" ) == -1 ) {
|
||||
// Add style the first time we need to.
|
||||
styleOut += "display:none;";
|
||||
}
|
||||
}
|
||||
// Only set style if it's different.
|
||||
if ( styleIn != styleOut ) {
|
||||
item.setAttribute( "style", styleOut );
|
||||
}
|
||||
}
|
||||
},
|
||||
// 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).
|
||||
setItemAttr : function ( 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 );
|
||||
}
|
||||
}
|
||||
},
|
||||
// Set context menu attribute according to like attribute of another node
|
||||
// (such as a broadcaster).
|
||||
setItemAttrFromNode : function ( item_id, attr, other_id ) {
|
||||
var elem = document.getElementById( other_id );
|
||||
if ( elem && elem.getAttribute( attr ) == "true" ) {
|
||||
this.setItemAttr( item_id, attr, "true" );
|
||||
} else {
|
||||
this.setItemAttr( item_id, attr, null );
|
||||
}
|
||||
},
|
||||
// Temporary workaround for DOM api not yet implemented by XUL nodes.
|
||||
cloneNode : function ( 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;
|
||||
},
|
||||
// Generate fully-qualified URL for clicked-on link.
|
||||
linkURL : function () {
|
||||
if (this.link.href) {
|
||||
return this.link.href;
|
||||
}
|
||||
// XXX TODO Relative URLs, XML Base
|
||||
var href = this.link.getAttributeNS("http://www.w3.org/1999/xlink","href");
|
||||
if (href == "") {
|
||||
throw "Empty href"; // Without this we try to save as the current doc, for example, HTML case also throws if empty
|
||||
}
|
||||
return href;
|
||||
},
|
||||
// Get text of link (if possible).
|
||||
linkText : function () {
|
||||
var text = this.gatherTextUnder( this.link );
|
||||
return text;
|
||||
},
|
||||
// Gather all descendent text under given document node.
|
||||
gatherTextUnder : function ( root ) {
|
||||
var text = "";
|
||||
var node = root.firstChild;
|
||||
var depth = 1;
|
||||
while ( node && depth > 0 ) {
|
||||
// See if this node is text.
|
||||
if ( node.nodeName == "#text" ) {
|
||||
// Add this text to our collection.
|
||||
text += " " + node.data;
|
||||
} else if ( node.tagName == "IMG" ) {
|
||||
// If it has an alt= attribute, use that.
|
||||
altText = node.getAttribute( "alt" );
|
||||
if ( altText && altText != "" ) {
|
||||
text = altText;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Find next node to test.
|
||||
// First, see if this node has children.
|
||||
if ( node.hasChildNodes() ) {
|
||||
// Go to first child.
|
||||
node = node.firstChild;
|
||||
depth++;
|
||||
} else {
|
||||
// No children, try next sibling.
|
||||
if ( node.nextSibling ) {
|
||||
node = node.nextSibling;
|
||||
} else {
|
||||
// Last resort is our next oldest uncle/aunt.
|
||||
node = node.parentNode.nextSibling;
|
||||
depth--;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Strip leading whitespace.
|
||||
text = text.replace( /^\s+/, "" );
|
||||
// Strip trailing whitespace.
|
||||
text = text.replace( /\s+$/, "" );
|
||||
// Compress remaining whitespace.
|
||||
text = text.replace( /\s+/g, " " );
|
||||
return text;
|
||||
},
|
||||
// Returns "true" if there's no text selected, null otherwise.
|
||||
isNoTextSelected : function ( event ) {
|
||||
// Not implemented so all text-selected-based options are disabled.
|
||||
return "true";
|
||||
},
|
||||
// Copy link/image url to clipboard.
|
||||
copyToClipboard : function ( text ) {
|
||||
// Get clipboard.
|
||||
var clipboard = this.getService( "@mozilla.org/widget/clipboard;1",
|
||||
"nsIClipboard" );
|
||||
|
||||
// Create tranferable that will transfer the text.
|
||||
var transferable = this.createInstance( "@mozilla.org/widget/transferable;1",
|
||||
"nsITransferable" );
|
||||
|
||||
if ( clipboard && transferable ) {
|
||||
transferable.addDataFlavor( "text/unicode" );
|
||||
// Create wrapper for text.
|
||||
var data = this.createInstance( "@mozilla.org/supports-wstring;1",
|
||||
"nsISupportsWString" );
|
||||
if ( data ) {
|
||||
data.data = text;
|
||||
transferable.setTransferData( "text/unicode", data, text.length * 2 );
|
||||
// Put on clipboard.
|
||||
clipboard.setData( transferable, null, Components.interfaces.nsIClipboard.kGlobalClipboard );
|
||||
}
|
||||
}
|
||||
|
||||
// Create a second transferable to copy selection. Unix needs this,
|
||||
// other OS's will probably map to a no-op.
|
||||
var transferableForSelection = this.createInstance( "@mozilla.org/widget/transferable;1",
|
||||
"nsITransferable" );
|
||||
|
||||
if ( clipboard && transferableForSelection ) {
|
||||
transferableForSelection.addDataFlavor( "text/unicode" );
|
||||
// Create wrapper for text.
|
||||
var selectionData = this.createInstance( "@mozilla.org/supports-wstring;1",
|
||||
"nsISupportsWString" );
|
||||
if ( selectionData ) {
|
||||
selectionData.data = text;
|
||||
transferableForSelection.setTransferData( "text/unicode", selectionData, text.length * 2 );
|
||||
// Put on clipboard.
|
||||
clipboard.setData( transferableForSelection, null,
|
||||
Components.interfaces.nsIClipboard.kSelectionClipboard );
|
||||
}
|
||||
}
|
||||
},
|
||||
// Determine if target <object> is an image.
|
||||
objectIsImage : function ( objElem ) {
|
||||
var result = false;
|
||||
// Get type and data attributes.
|
||||
var type = objElem.getAttribute( "type" );
|
||||
var data = objElem.getAttribute( "data" );
|
||||
// Presume any mime type of the form "image/..." is an image.
|
||||
// There must be a data= attribute with an URL, also.
|
||||
if ( type.substring( 0, 6 ) == "image/" && data && data != "" ) {
|
||||
result = true;
|
||||
}
|
||||
return result;
|
||||
},
|
||||
// Extract image URL from <object> tag.
|
||||
objectImageURL : function ( objElem ) {
|
||||
// Extract url from data= attribute.
|
||||
var data = objElem.getAttribute( "data" );
|
||||
// Make it absolute.
|
||||
return this.makeURLAbsolute( objElem.ownerDocument, data );
|
||||
},
|
||||
// Convert relative URL to absolute, using document's <base>.
|
||||
makeURLAbsolute : function ( doc, url ) {
|
||||
// Construct nsIURL.
|
||||
var baseURL = this.createInstance( "@mozilla.org/network/standard-url;1", "nsIURL" );
|
||||
// Initialize from document url.
|
||||
baseURL.spec = doc.location.href;
|
||||
// Look for <base> tag.
|
||||
var baseTags = doc.getElementsByTagName( "BASE" );
|
||||
if ( baseTags && baseTags.length ) {
|
||||
// Reset base URL using href attribute of <base> tag.
|
||||
var href = baseTags[ baseTags.length - 1 ].getAttribute( "href" );
|
||||
baseURL.spec = baseURL.resolve( href );
|
||||
}
|
||||
// Finally, convert argument url using base.
|
||||
var result = baseURL.resolve( url );
|
||||
return result;
|
||||
},
|
||||
// Save specified URL in user-selected file.
|
||||
savePage : function ( url, doNotValidate ) {
|
||||
var postData = null; // No post data, usually.
|
||||
// Default is to save current page.
|
||||
if ( !url ) {
|
||||
url = window._content.location.href;
|
||||
// Post data comes from appcore.
|
||||
if ( window.appCore ) {
|
||||
postData = window.appCore.postData;
|
||||
}
|
||||
}
|
||||
// Use stream xfer component to prompt for destination and save.
|
||||
var xfer = this.getService( "@mozilla.org/appshell/component/xfer;1",
|
||||
"nsIStreamTransfer" );
|
||||
try {
|
||||
xfer.SelectFileAndTransferLocationSpec( url, window, "", "", doNotValidate, postData );
|
||||
} catch( exception ) {
|
||||
// Failed (or cancelled), give them another chance.
|
||||
dump( "SelectFileAndTransferLocationSpec failed, rv=" + exception + "\n" );
|
||||
}
|
||||
return;
|
||||
},
|
||||
// Parse coords= attribute and return array.
|
||||
parseCoords : function ( area ) {
|
||||
return [];
|
||||
},
|
||||
toString : function () {
|
||||
return "contextMenu.target = " + this.target + "\n" +
|
||||
"contextMenu.onImage = " + this.onImage + "\n" +
|
||||
"contextMenu.onLink = " + this.onLink + "\n" +
|
||||
"contextMenu.link = " + this.link + "\n" +
|
||||
"contextMenu.inFrame = " + this.inFrame + "\n" +
|
||||
"contextMenu.hasBGImage = " + this.hasBGImage + "\n";
|
||||
},
|
||||
isTargetATextField : function ( node )
|
||||
{
|
||||
if (node.tagName.toUpperCase() == "INPUT") {
|
||||
var attrib = node.getAttribute("type").toUpperCase();
|
||||
return( (attrib != "IMAGE") &&
|
||||
(attrib != "PASSWORD") &&
|
||||
(attrib != "CHECKBOX") &&
|
||||
(attrib != "RADIO") &&
|
||||
(attrib != "SUBMIT") &&
|
||||
(attrib != "RESET") &&
|
||||
(attrib != "FILE") &&
|
||||
(attrib != "HIDDEN") &&
|
||||
(attrib != "RESET") &&
|
||||
(attrib != "BUTTON") );
|
||||
} else {
|
||||
return(node.tagName.toUpperCase() == "TEXTAREA");
|
||||
}
|
||||
}
|
||||
};
|
|
@ -0,0 +1,61 @@
|
|||
<!-- Context Menu -->
|
||||
<!ENTITY blockImageCmd.label "Block Image from Loading">
|
||||
<!ENTITY blockImageCmd.accesskey "k">
|
||||
<!ENTITY openLinkCmd.label "Open Link in New Window">
|
||||
<!ENTITY openLinkCmd.accesskey "o">
|
||||
<!ENTITY editLinkCmd.label "Edit Link in Composer">
|
||||
<!ENTITY editLinkCmd.accesskey "e">
|
||||
<!ENTITY openFrameCmd.label "Open Frame in New Window">
|
||||
<!ENTITY openFrameCmd.accesskey "o">
|
||||
<!ENTITY showOnlyThisFrameCmd.label "Show Only This Frame">
|
||||
<!ENTITY showOnlyThisFrameCmd.accesskey "w">
|
||||
<!ENTITY goBackCmd.label "Back">
|
||||
<!ENTITY goBackCmd.accesskey "b">
|
||||
<!ENTITY goForwardCmd.label "Forward">
|
||||
<!ENTITY goForwardCmd.accesskey "f">
|
||||
<!ENTITY reloadCmd.label "Reload">
|
||||
<!ENTITY reloadCmd.accesskey "r">
|
||||
<!ENTITY reloadCmd.commandkey "r">
|
||||
<!ENTITY stopCmd.label "Stop">
|
||||
<!ENTITY stopCmd.accesskey "s">
|
||||
<!ENTITY reloadFrameCmd.label "Reload Frame">
|
||||
<!ENTITY reloadFrameCmd.accesskey "r">
|
||||
<!ENTITY viewPageSourceCmd.label "View Page Source">
|
||||
<!ENTITY viewPageSourceCmd.accesskey "v">
|
||||
<!ENTITY viewFrameSourceCmd.label "View Frame Source">
|
||||
<!ENTITY viewFrameSourceCmd.accesskey "v">
|
||||
<!ENTITY viewPageInfoCmd.label "View Page Info">
|
||||
<!ENTITY viewPageInfoCmd.accesskey "i">
|
||||
<!ENTITY viewFrameInfoCmd.label "View Frame Info">
|
||||
<!ENTITY viewFrameInfoCmd.accesskey "i">
|
||||
<!ENTITY viewImageCmd.label "View Image">
|
||||
<!ENTITY viewImageCmd.accesskey "w">
|
||||
<!ENTITY bookmarkPageCmd.label "Bookmark this Page">
|
||||
<!ENTITY bookmarkPageCmd.accesskey "b">
|
||||
<!ENTITY bookmarkLinkCmd.label "Bookmark this Link">
|
||||
<!ENTITY bookmarkLinkCmd.accesskey "b">
|
||||
<!ENTITY savePageCmd.label "Save As...">
|
||||
<!ENTITY savePageCmd.accesskey "s">
|
||||
<!ENTITY savePageCmd.commandkey "s">
|
||||
<!ENTITY saveFrameCmd.label "Save Frame As...">
|
||||
<!ENTITY saveFrameCmd.accesskey "f">
|
||||
<!ENTITY saveLinkCmd.label "Save Link As...">
|
||||
<!ENTITY saveLinkCmd.accesskey "a">
|
||||
<!ENTITY saveImageCmd.label "Save Image As...">
|
||||
<!ENTITY saveImageCmd.accesskey "a">
|
||||
<!ENTITY saveBGImageCmd.label "Save Background Image As...">
|
||||
<!ENTITY saveBGImageCmd.accesskey "a">
|
||||
<!ENTITY copyCmd.label "Copy">
|
||||
<!ENTITY copyCmd.accesskey "c">
|
||||
<!ENTITY selectAllCmd.label "Select All">
|
||||
<!ENTITY selectAllCmd.accesskey "l">
|
||||
<!ENTITY copyLinkCmd.label "Copy Link Location">
|
||||
<!ENTITY copyLinkCmd.accesskey "n">
|
||||
<!ENTITY copyImageCmd.label "Copy Image Location">
|
||||
<!ENTITY copyImageCmd.accesskey "m">
|
||||
<!ENTITY pasteCmd.label "Paste">
|
||||
<!ENTITY pasteCmd.accesskey "p">
|
||||
<!ENTITY captureCmd.label "Save Form Data">
|
||||
<!ENTITY prefillCmd.label "Prefill Form">
|
||||
<!ENTITY cutCmd.label "Cut">
|
||||
<!ENTITY cutCmd.accesskey "u">
|
Загрузка…
Ссылка в новой задаче