Reputation: 11635
I would like to allow the user of my XULRunner based app to be able to do copy/paste via a context menu. Keyboard shortcuts Ctrl-C and Ctrl-V are already working fine
Upvotes: 1
Views: 1315
Reputation: 580
One more example for "Copy" context menu in XULRunner under SWT Browser (code was implemented for Eclipse v3.5.1, XULRunner v1.8.1.3):
Browser browser = new Browser(parent, style | SWT.MOZILLA);
Menu menu = new Menu(browser);
MenuItem item = new MenuItem(menu, SWT.NONE);
item.setText("Copy");
item.addSelectionListener(new SelectionListener() {
@Override
public void widgetSelected(SelectionEvent e) {
nsIWebBrowser webBrowser = (nsIWebBrowser) browser.getWebBrowser();
nsIInterfaceRequestor req = (nsIInterfaceRequestor) webBrowser.queryInterface(nsIInterfaceRequestor.NS_IINTERFACEREQUESTOR_IID);
nsIDocShell docShell = (nsIDocShell) req.getInterface(nsIDocShell.NS_IDOCSHELL_IID);
nsIClipboardCommands cmds = (nsIClipboardCommands) docShell.queryInterface(nsIClipboardCommands.NS_ICLIPBOARDCOMMANDS_IID);
cmds.copySelection();
}
@Override
public void widgetDefaultSelected(SelectionEvent e) {
}
});
browser.setMenu(menu);
Upvotes: 1
Reputation: 641
Here it is without flash. The getInputSelection function is from here: Is there an Internet Explorer approved substitute for selectionStart and selectionEnd?.
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<window id="mywin" title="my app"
width="800" height="600" persist="screenX screenY width height sizemode"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<popupset>
<menupopup id="clipmenu">
<menuitem label="Copy" oncommand="copy()"/>
<menuitem label="Paste" oncommand="paste();"/>
</menupopup>
</popupset>
<browser
type="content-primary"
src="http://127.0.0.1/"
flex="1"
disablehistory="true"
id="browserId"
context="clipmenu"
/>
<script>
<![CDATA[
function copy()
{
var tabBrowser = document.getElementById("browserId");
var selectedTagName = tabBrowser.contentWindow.document.activeElement.tagName;
var windowObj;
if(selectedTagName == "IFRAME")
{
windowObj = tabBrowser.contentWindow.frames[tabBrowser.contentWindow.document.activeElement.name];
}
else
{
windowObj = document.getElementById("browserId").contentWindow;
}
var selectedText = windowObj.getSelection();
if(!selectedText || selectedText == "")
{
var focused = windowObj.document.activeElement;
if(focused && focused.value)
{
selectedText = getSelectionFromInput(focused);
}
}
//alert(selectedText + "---");
const clipHelper = Components.classes["@mozilla.org/widget/clipboardhelper;1"].getService(Components.interfaces.nsIClipboardHelper);
clipHelper.copyString(selectedText);
}
function getSelectionFromInput(focused)
{
var focusedValue = focused.value;
var sel = getInputSelection(focused);
var selectedText = "";
if(focusedValue.length == (sel.end))
{
selectedText = focusedValue.substring(sel.start);
}
else
{
selectedText = focusedValue.substring(sel.start, (sel.end));
}
return selectedText;
}
function paste()
{
var clip = Components.classes["@mozilla.org/widget/clipboard;1"].getService(Components.interfaces.nsIClipboard);
var trans = Components.classes["@mozilla.org/widget/transferable;1"].createInstance(Components.interfaces.nsITransferable);
trans.addDataFlavor("text/unicode");
clip.getData(trans, clip.kGlobalClipboard);
var str = new Object();
var len = new Object();
trans.getTransferData("text/unicode",str,len);
str = str.value.QueryInterface(Components.interfaces.nsISupportsString);
str = str.data.substring(0, len.value / 2);
var focused = document.commandDispatcher.focusedElement;
var focusedValue = focused.value;
var sel = getInputSelection(focused);
focused.value = focusedValue.substring(0,sel.start) + str + focusedValue.substring(sel.end);
}
function getInputSelection(el) {
var start = 0, end = 0, normalizedValue, range,
textInputRange, len, endRange;
if (typeof el.selectionStart == "number" && typeof el.selectionEnd == "number") {
start = el.selectionStart;
end = el.selectionEnd;
} else {
range = document.selection.createRange();
if (range && range.parentElement() == el) {
len = el.value.length;
normalizedValue = el.value.replace(/\r\n/g, "\n");
// Create a working TextRange that lives only in the input
textInputRange = el.createTextRange();
textInputRange.moveToBookmark(range.getBookmark());
// Check if the start and end of the selection are at the very end
// of the input, since moveStart/moveEnd doesn't return what we want
// in those cases
endRange = el.createTextRange();
endRange.collapse(false);
if (textInputRange.compareEndPoints("StartToEnd", endRange) > -1) {
start = end = len;
} else {
start = -textInputRange.moveStart("character", -len);
start += normalizedValue.slice(0, start).split("\n").length - 1;
if (textInputRange.compareEndPoints("EndToEnd", endRange) > -1) {
end = len;
} else {
end = -textInputRange.moveEnd("character", -len);
end += normalizedValue.slice(0, end).split("\n").length - 1;
}
}
}
}
return {
start: start,
end: end
};
}
]]>
</script>
</window>
Updated to support iframes.
Upvotes: 1
Reputation: 18029
Create menu using the code below.
<popupset>
<menupopup id="clipmenu">
<menuitem label="Copy" oncommand="copy();"/>
<menuseparator/>
<menuitem label="paste" oncommand="paste();"/>
</menupopup>
</popupset>
<browser type="content" src="chrome://myapp/content/theme1/index.html" flex="1" context="clipmenu"/>
Connect it to whatever you want, here am making it the context menu of the browser element by giving the id of menu in the context attribute of the browser element.
Then for each menu you can give the command to execute in oncommand event. We have given the function copy and paste.
Then write the code to copy text from whatever element you want or if you want to copy the selected data only.
See the below link for copying command.
http://www.deluxeblogtips.com/2010/06/javascript-copy-to-clipboard.html
Upvotes: 1