I am trying to write a JavaScript script to add to greasemonkey that adds a button after an element. The onClick for this button should copy the parents element text to the keyboard. I have seen plenty of examples that copy already selected text to the clipboard such as this:
<SCRIPT LANGUAGE="JavaScript">
<!-- Begin
function copyit(theField) {
var selectedText = document.selection;
if (selectedText.type == 'Text') {
var newRange = selectedText.createRange();
theField.focus();
theField.value = newRange.text;
} else {
alert('Alert: Select The text in the textarea then click on this button');
}
}
// End -->
</script>
<input onclick="copyit(this.form.text_select)" type="button" value="Click Here to Copy the Highlighted Text" name="copy_button">
Found here.
I have also found that you can select text in input elements. I have tried combining both techniques, as well as many others with no viable solution yet. I am not even sure why the code above copies to the clipboard. Does anyone have a solution to this?
If you took the time to read the full article, the author states this doesn't work for Firefox...
Actually, I think it doesn't even work for IE, as it does nothing related to the clipboard!
There is a technique using Flash, because by default, Firefox inhibits clipboard access for security reasons.
Otherwise, the classical way to do copy is:
var tc = textToCopy.replace(/\n\n/g, '\n');
if (window.clipboardData) // IE
{
window.clipboardData.setData("Text", tc);
}
else
{
unsafeWindow.netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
const clipboardHelper = Components.classes
["#mozilla.org/widget/clipboardhelper;1"].
getService(Components.interfaces.nsIClipboardHelper);
clipboardHelper.copyString(tc);
}
after enabling copy (for a given site).
Are you sure your example works? It does not in my browser. But take a look at the following page: http://www.jeffothy.com/weblog/clipboard-copy/
Related
I was able to get the highlighted text out of a textarea by recording onselect and storing the beginning and end each time. Then, when I click a button, I build the substring myself. Isn't there a simpler way of simply querying the selection?
I was kind of expecting that there would be methods in html5 dom for all these things, something like:
textarea.getSelectedStart()
textarea.getSelectedEnd();
textArea.setSelected(start,end);
Also, is there a way of programmatically deselecting text in a textarea?
I am putting in code based on the first solution below. This sort of works, but has a weird problem:
<script language=javascript>
function replaceCLOZE(code, questionType) {
var v = code.value;
var s = code.selectionStart;
var e = code.selectionEnd;
var t = v.substr(s, e-s);
var rep = "{:" + questionType + ":="+t+"}";
code.value = v.substr(0,s) + rep + v.substr(e,v.length-e+1);
}
function shortAnswer(code) {
replaceCLOZE(code, "SA");
}
function shortAnswerCaseSensitive(code) {
replaceCLOZE(code, "SAC");
}
function multipleChoice(code) {
replaceCLOZE(code, "MC");
}
The text area does in fact have attributes code.selectionStart and code.selectionEnd. But the code above, which now works, sets the highlighted text on the screen to be the first word in the textarea. Mind you, the selectionStart is still correct, but what is actually highlighted in Firefox is wrong.
In Chrome it works fine. Maybe this is just a bug in firefox or is there something else which should be done to properly update the textarea visually?
Following is simple way to get selected text of textarea of html. Still not clear what you want as following method simply will give you selected text in alert.
<html><head>
<script>
function alertme(){
var textarea = document.getElementById("textArea");
var selection = (textarea.value).substring(textarea.selectionStart,textarea.selectionEnd);
alert (selection);
}
</script>
</head>
<body>
<p><textarea class="noscrollbars" id="textArea"></textarea></p>
<button onclick="alertme()">Click me</button>
</body></html>
When you select text, the button will alert you what you have selected. selectionStart gives you starting point and selectionEnd gives you end point, while substring needs three arguments string, starting point and ending point.
I see that when I try to read the value from a textarea field when its onpaste function is called, I get the old value of the field (the one before the paste operation), not the new value (the one after the paste operation).
Here is a demonstration of this behaviour: http://jsfiddle.net/qsDnr/
A copy of the code follows:
<!DOCTYPE html>
<html>
<head>
<title>On Paste</title>
<script type="text/javascript">
var textareaElement;
var previewElement;
function update()
{
previewElement.innerHTML = textareaElement.value;
}
window.onload = function() {
textareaElement = document.getElementById('textarea');
previewElement = document.getElementById('preview');
textareaElement.onpaste = update
}
</script>
</head>
<body>
<textarea id="textarea">
</textarea>
<div id="preview">
</div>
</body>
</html>
You can confirm the behaviour with the following steps.
Copy the string foo to your clipboard.
Right-click on the textarea field and select 'Paste'. Nothing appears in the div element.
Right-click on the textarea field and select 'Paste' again. foo appears in the div element.
Since I want the div element to always show what was updated in the textarea element with the paste operation, the desired output is foo and foo foo in step 2 and step 3 respectively.
One way I have managed to get the desired output is by delaying the update() function call with window.setTimeout(), so instead of
textareaElement.onpaste = update
I have got
textareaElement.onpaste = function() {
window.setTimeout(update, 100);
};
this time (demo: http://jsfiddle.net/cwpLS/). This does what I want. However, this feels more like a workaround rather than a straightforward way of doing what I want. I would like to know if there is any alternate or better way to do this.
I'm pretty sure that you setTimeout solution is the only way to achieve the desired effect, or try to access the clipboard object - which can get messy if you're going for cross-browser & old browser support.
There is no direct way to do it in cross browser. See the link below about the behaviour in firefox.
Mozilla
There is currently no DOM-only way to obtain the text being pasted; you'll have to use an nsIClipboard to get that information.
Also please have a look at the stackoverflow link which discuss about other possibilities.
I've got a rich text editor in an iframe with designMode that does syntax highlighting for small blocks of text. I'd like it to update the highlighting on keyup, but messing with the DOM causes the frame to blur, thus every time you push a key the caret disappears and you can't type anymore. That wouldn't be a problem if the parser could remember where the caret is, and then refocus the iframe and replace the caret. I've read up on getSelection() and its relatives, but apparently onkeyup removes the selection, at least in Chrome - calling getSelection() inside an onkeyup always yields a null selection. Is there a way around this?
This is what I have:
<iframe>
<html>
<head>
<script>
function parse() {
if(window.getSelection().type != 'None') {
var range = window.getSelection().getRangeAt(0);
}
var text = document.body.textContent;
//Parse text, output is stored in newtext
document.body.innerHTML = newtext;
document.body.focus();
if(range) {
window.getSelection().removeAllRanges();
window.getSelection().addRange(range);
}
}
</script>
</head>
<body onload="document.designMode = 'on'; document.onkeyup = parse;">
Text entered appears here
</body>
</html>
</iframe>
I would recommend to use some other code highlighter. Like CodeMirror for example.
not sure if you're open to using a JS framework, but mootools has some pretty nifty selection utilities (e.g., http://mootools.net/docs/more/Element/Element.Forms#Element:getCaretPosition)
Say I want to have the 'bold' option selected by default when the editor is initialized. How would I do that?
EDIT: A solution working with what Thariama answered is the following. I discovered that having the <p> tag left in there screwed with selecting other options, like with different headlines, and as I have no need for a <p> tag in this particular editor I did this in order to get <h1> by default:
setup: function(ed) {
ed.onInit.add(function(ed) {
if ($('p', ed.getDoc()).length > 0) {
$('p', ed.getDoc()).remove();
$('<h1><br mce_bogus="1" /></h1>').appendTo($('body', ed.getDoc()));
}
});
}
This works great even when the user jumps between selection options in a select.
EDIT2: This seems to work if you do need the <p> tag. This makes it bold by default:
setup: function(ed) {
ed.onInit.add(function(ed) {
if ($('p', ed.getDoc()).children().length == 1 && $('p', ed.getDoc()).children(':first').is('br')) {
$('p', ed.getDoc()).html('<b><br mce_bogus="1" /></b>');
}
});
}
Rather than doing it when the user enters it, why not output the values inside a bold tag when you output the data to the user outside of tinyMCE? That way, the user has no ability to override the option as they would if you simply had a tag inside.
As an aside, if you're using TinyMCE for a wysiwg web editor in an environment where users first generate code in Microsoft Word, there are significant issues with getting "junk" word code in via paste. Tiny's solution is a "paste from word" button, which users seem to often ignore -- I've deployed Tiny in 50+ business websites, and it's been a major issue with a majority of the clients using those sites. I switched over to CKEditor, which does word code-stripping on the FRONT end, and all's been well. People have their preferences, and I even liked using Tiny more. But Word Code issues have become a dealbreaker for me and I won't install Tiny any more.
The procedure of choice depends on many factors. If you have an empty tinymce editor you can initialize your editor with the following content
<p><strong><strong></p>
Please update your question regarding your use case.
EDIT: This might work better for you. Add this handler to one of your own plugins.
It checks for all paragraphs (if your tinymce uses divs you need to alter this piece of code)
and wraps the inner HTML into b-tags (you might want to use strong-tags).
ed.onInit.add(function(ed){
ps = ed.getDoc().getElementsByTagName('p');
for (var i=0; i < ps.length ; i++) {
ps[i].innerHTML = '<b>'+ps[i].innerHTML+'</b>';
}
});
Another option you have is to not use an own plugin, but to use the setup parameter when initializing tinymce:
setup : function(ed) {
ed.onInit.add(function(ed){
ps = ed.getDoc().getElementsByTagName('p');
for (var i=0; i < ps.length ; i++) {
ps[i].innerHTML = '<b>'+ps[i].innerHTML+'</b>';
}
});
},
Before any asks, I did research this thoroughly and the answer has not been post here previously.
I want to send some plain text configuration text to the clipboard with Javascript. The text will consist of multiple commands, one command per line, so that the user may then past into a configuration file on his PC (call it "myconfig.ini") using a text editor (most commonly, Notepad.exe).
I tried the following:
var cCRLF = String.fromCharCode(10,13);
var cText = 'This is command line 1'+cCRLF;
cText += 'This is command line 2'+cCRLF;
cText += 'This is command line 3'+cCRLF;
cText += 'This is command line 4';
window.clipboardData.setData('Text', cText);
but when I execute and paste into notepad, I don't get individual lines and the line return character (cCRLF) is not viewable (that nasty little box character appears).
Does someone have a solution for this?
The solution is to use back-tick (` `)
alert(`string text line 1
string text line 2`);
For reference:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/template_strings
I would suggest using some other method than the clipboard for sending data to the user. This method only works in IE and can be disabled (and newer IE versions prompt first): Get clipboard data as array in javascript
A CSS popup box (which the user can copy from themselves) would probably be a nicer (and cross-platform) solution. This might help: http://www.pat-burt.com/web-development/how-to-do-a-css-popup-without-opening-a-new-window/
I think i did find a solution. It's a bit weird, but hey, it's for IE. It's a modified snippet I found on stackoverflow.
<body>
<a href="#" onclick='test("This\nIS\nA\nTEST")'>TEST</a>
<div id="cb" style="position: absolute; left: -2000px"></div>
</body>
<script>
function test(cText) {
cText= cText.replace(/\n\r?/g, "<br>");
// create an editable DIV and append the HTML content you want copied
var editableDiv = document.getElementById("cb");
with (editableDiv) {
contentEditable = true;
}
editableDiv.innerHTML= cText;
// select the editable content and copy it to the clipboard
var r = document.body.createTextRange();
r.moveToElementText(editableDiv);
r.select();
r.execCommand("Copy");
// deselect, so the browser doesn't leave the element visibly selected
r.moveToElementText(document.body);
r.select();
}
</script>