Javascript code to insert text at cursor position in Firefox? - javascript

The use case
When I'm typing a query into a search engine, sometimes it's useful to quote
a part of the query, so the engine doesn't bother me with useless suggestions.
The task
This operation is so frequent, that I want to do this with a shortcut.
The shortcut part isn't the issue, there's a way to assign a shortcut to a bookmarklet.
What I don't know how to do is
Get the current text area. The only thing I know about it is that the cursor is there.
I cannot assume any ids etc. Also, I don't want to install any hooks.
Insert "", and go backwards one character.
I'm expecting a one/two liner that I can place in a bookmarklet.

The solution
Since no one wanted to answer, and I'm just a novice in JavaScript,
I decided to see if there's a plugin that does close to what I want.
The choice fell to Firemacs,
since I'm using it anyway.
The code to go backward one char is simplicity itself:
goDoCommand('cmd_charPrevious');
However, the command to insert text didn't work.
But the command to paste is simple again:
goDoCommand('cmd_paste');
Now it only remains to put '""' in the clipboard. This one isn't easy:
var str = Components.classes["#mozilla.org/supports-string;1"]
.createInstance(Components.interfaces.nsISupportsString);
str.data = '""';
var trans = Components.classes["#mozilla.org/widget/transferable;1"]
.createInstance(Components.interfaces.nsITransferable);
trans.addDataFlavor("text/unicode");
trans.setTransferData("text/unicode",str, str.data.length * 2);
var clipid = Components.interfaces.nsIClipboard;
var clip = Components.classes["#mozilla.org/widget/clipboard;1"]
.getService(clipid);
clip.setData(trans,null,clipid.kGlobalClipboard);
Then I just patched this code into the extension instead of the "Ctrl-h" binding,
which I don't use. Problem solved. Now I can insert a pair of quotes very fast in Firefox.

Related

How to remove empty lines in a google doc using the script editor (Google Docs add-ons)?

I am creating a Google Docs add-on, and one of the features I am trying to create is a feature that reduces the number of empty lines between two paragraphs.
So, for instance, if I have 2 paragraphs with 5 empty/blank lines between them, I want the feature to reduce the number of empty lines to 1.
Essentially, I need a way to detect an empty line. I've looked at the API, and think I need to use the replaceText() method which searches for a regex pattern. However, I've tried it, and it didn't work (perhaps I'm using an incorrect patter, i dont know).
Can anyone help me in finding a way to detect an empty line? Thanks.
EDIT:
I just found out that Google Docs don't support all patterns of regex. Here is that link: https://support.google.com/analytics/answer/1034324?hl=en . I'm not familiar with regex. Can anyone provide an alternative that works in Google Docs.
Written and tested the below function, here are the steps to make it work
Copy the text from here Lorem Ipsum Google Doc, to a new Google Doc
Add the below snippet to your Tools > Script editor > project
Comments inline
// Regular expressions with the following special characters are not supported,
// as they can cause delays in processing your email: * (asterisk), + (plus sign)
// So RegEx is not applicable since you can't use "\s*", we need to find another solution
// A row/line is a Paragraph, weird right? So now you iterate through the rows
// Trim paragraph (row), if it's empty, then you can delete it.
function removeEmptyLines() {
var doc = DocumentApp.getActiveDocument();
Logger.log("Before:\n", doc.getBody().getText());
var paragraphs = doc.getBody().getParagraphs();
// Iterating from the last paragraph to the first
for (var i=paragraphs.length-1; i>=0; i--){
var line = paragraphs[i];
if ( ! line.getText().trim() ) {
// Paragraph (line) is empty, remove it
line.removeFromParent()
Logger.log("Removed: ", i);
}
}
Logger.log("After:\n", doc.getBody().getText());
}
References
https://developers.google.com/apps-script/reference/document/text#replaceText(String,String)
https://support.google.com/a/answer/1371415?hl=en
https://stackoverflow.com/a/3012832/5285732

Print html to a surface to be copied

I stored an table's html as a text, using this code.
var Data = document.getElementsByClassName("result")[0].innerHTML;
I am able to observe the selected part using console.log, however, I wish to extract this data to be copied and used outside.
So I tried alert(Data), but it does not offer a good surface to copy the data (it does work though, however I cannot use right click on the pop-up window)
I also tried to programmatically copy the data to the clipboard, but it seems, it only works on selected text data.
Is there a better way to extract such data to be used outside ?
Note: I am using a firefox bookmark to execute javascript. But I expect the code to work also in the other browsers.
Edit: I tried the method suggested in the comments, however in firefox, I got an error.
document.execCommand(‘cut’/‘copy’) was denied because it was not called from inside a short running user-generated event handler.
So rather than copying with that command, printing to a surface seems a better choice, if possible. The linked question does not solve my issue.
Edit2: window.prompt did a much better job, however it rocked my world by pressing the text to a single line. I still should be able to parse it programmatically, but if there is a better answer, I wish to learn it.
Below is my solution to keep multiple lines.
It creates one temp 'textarea', then remove it after select()->copy.
function triggercopy() {
var target_obj = document.getElementById('test1');
var copy_text = target_obj.innerHTML; //replace with your actual data.
var hidden_obj = document.createElement("textarea");
hidden_obj.value = copy_text;
document.body.insertBefore(hidden_obj,target_obj);
console.log('prepare:' + copy_text);
hidden_obj.select();
document.execCommand("copy");
document.body.removeChild(hidden_obj);
console.log('already copied:' + copy_text);
}
Text3as
dfsadf
<a id="test1" onclick="triggercopy();">Text3as
dfsadf</a>
I found two methods best suit my interests.
First, window.prompt:
var Data = document.getElementsByClassName("result")[0].innerHTML;
function copyToClipboard(text) {
window.prompt("Copy data.", text);
}
copyToClipboard(Data)
This is a good method, taken from a suggested answer. This puts the data into a single-line text field. And in an interesting manner, when written without a function, executes document.write(Data) when clicked OK, this does not happen when written in a function as above.
Second, document.write:
var target = document.getElementsByClassName("resultTable striped")[0].outerHTML;
document.open('text/plain');
document.write(target);
I first tried to open a new tab with the desired content, however encountered with the issue of pop-up blockers and non-plain text html data (formatted html instead of the desired table html data). This solves both issues.

Setting a BBEdit insertion point with JXA

I am trying to translate a few Applescript (AS) into Javascript (JXA) for BBedit.
It's been a fun little thing to knock some rust off, but I'm stumped.
With AS I can set an insertion point into a BBEdit document thusly;
tell application "BBEdit"
activate
tell text 1 of window 1
select insertion point before line 40
end tell
end tell
I'm totally stumped when it comes to JXA. I've been poking around in the line objects but I can't find a insertsionPoint property.
You can access selection properties like so;
currentLine = bbedit.selection().startline().
But it is read only. So I think you need access to that select method if you want to set a selection or insertion point. I have no clue how, or if you can with JXA.
Anyone know how to set a BBEdit insertion point and/or selection with JXA?
Thanks.
JXA doesn't implement insertion reference forms (before/after/beginning/end). Relative (previous…/next…) and range (from…to…) specifiers are also borked, and filter (whose…) clauses are horrible too. Lots of non-trivial stuff that works fine in AS breaks in JXA: like Apple's earlier Scripting Bridge API, JXA was half-baked when shipped and immediately abandoned to rot.
Crap like this is why I recommend sticking to AppleScript. The language may stink, but it's the only [marginally] supported option that actually implements Apple events right. Normally I'd recommend calling into AppleScript from other languages via the AppleScript-ObjC bridge as the least sucky solution, but Apple have managed to break that too in 10.13.
(If you enjoy living dangerously, NodeAutomation provides non-broken Apple event support for Node.js, but with Apple abandoning AppleScript automation I don't want to waste anyone's time promoting or supporting it, so caveat emptor.)
Below is an example of using Javascript (JXA) for BBedit insertion point object and select method. BBEdit does seem to work with JXA but there is absolutely no documentation for JXA from BBEdit and very little information on the web. Below is some code that I came up with after spending hours of trial and error. So I hope it helps.
(() => {
/* Example to show using insertionPoints with BBEdit
the script adds new text to the last line of a BBEdit text document
*/
const strPath = '/Users/bartsimpson/Library/Mobile Documents/com~apple~ScriptEditor2/Documents/insertionPointsExample.txt';
const BBEdit = Application('BBEdit');
const docs = BBEdit.textDocuments;
//use select in case there are multiple BBEdit documents open
BBEdit.open(Path(strPath)).select();
let doc = docs[0];
let insertionPoints = doc.characters.insertionPoints;
let lines = doc.characters.lines;
let indexLastChar = doc.characters.length;
let indexLastLine = lines.length-1;
//last line in doc is blank
if (lines[indexLastLine].length() == 0){
insertionPoints[indexLastChar].contents = 'some new text5';
indexLastChar = doc.characters.length; //update after adding text
insertionPoints[indexLastChar].select(); //puts cursor end of last line
}
//last line in doc has text so add a new line first
else {
insertionPoints[indexLastChar].contents = '\n';
insertionPoints[indexLastChar+1].contents = 'some new text6';
indexLastChar = doc.characters.length; //update after adding text
insertionPoints[indexLastChar].select(); //puts cursor end of last line
}
})()

Using grease/tampermonkey (or another extension) to omit certain characters inside web elements

Firstly, I apologize if my terminology here isn't the most accurate; I'm very much a novice when it comes to programming. A forum I frequent has added a bunch of unneccessary, "glitchy" images and text to the page as a part of some promotion, but the result is that the forum is now difficult to use and read. I was able to script out most of it using adblock, but there's one last bit that shows up inside the forum elements themselves, and adblock wants to remove the whole element (which breaks the forum). This is part of the code in question, with the URLs changed:
<td class="windowbg" valign="middle" width="42%">&blk34;&blk34;&blk34;&blk34;&blk34;
Thread title <span class="smalltext"></span><img src="example.com/forumicon.gif"></td>
As you can see, the ▓ character shows up a bunch of times for no reason. Is there a way to make my browser ignore this character when it's inside of an element? If there's a way to do this using AdBlock, I am not smart enough to see it.
Here's one way to do it, using a NodeIterator:
var iter = document.createNodeIterator( document.body, NodeFilter.SHOW_TEXT );
var node;
while (node = iter.nextNode()) {
node.textContent = node.textContent.replace( /[\u2580-\u259f]+/g, '' );
}
This is just plain JavaScript code; you can paste it into the Firefox / Chrome JS console to test it. The regexp /[\u2580-\u259f]+/ matches any sequence of characters in the "Block Elements" Unicode block, including U+2593 Dark Shade (▓). You may want to tweak the regexp to match the characters you want to remove. (Tip: If you don't know what the codes for those characters are, copy and paste them into the "UTF8 String" box on this page.)
Ps. If these characters that you want to remove occur only in a certain part of the document, you can make this code a bit more efficient by replacing the root node (document.body above) with the specific DOM node that you want to remove the characters from. To find the nodes you want, you can use e.g. document.getElementById() or, more generally, document.querySelector() (or even document.querySelectorAll() and loop over the results).

Javascript: Hijack Copy?

I was just reading the Times online and I wanted to copy a bit of text from the article and IM it to a friend, but I noticed when I did so, it automatically appended the link back to the article in what I had copied.
This is not a feature of my IM client, so I assume this happened because of some javascript on Times website.
How would I accomplish this if I wanted to implement it on my site? Basically, I would have to hijack the copy operation and append the URL of the article to the end of the copied content, right? Thoughts?
Here's the article I was reading, for reference: http://www.time.com/time/health/article/0,8599,1914857,00.html
It's a breeze with jQuery (which your referenced site is using):
$("body").bind('copy', function(e) {
// The user is copying something
});
You can use the jQuery Search & Share Plugin which does this exact thing whenever somebody copies more than 40 chars from your site: http://www.latentmotion.com/search-and-share/
The site that you referenced is apparently using a service called Tynt Insight to accomplish this though.
They are using the free service Tynt. If you want to accomplish the same thing, just use the same service.
What browser are you using (and what version)?
In some newer browsers, the user is either asked if a website can access the clipboard, or its simply not allowed. In other browsers (IE 6, for example), it is allowed, and websites can easily read from and write to your copy clipboard.
Here is the code (IE only)
clipboardData.setData("Text", "I just put this in the clipboard using JavaScript");
The "Copy & Paste Hijacker" jQuery plugin does exactly what you want and seems better suited for your purposes than Tynt or Search & Share: http://plugins.jquery.com/project/copypaste
You can easily format the copied content, specify max or min characters, and easily include the title of the page or the URL in the copied content exactly where you want.
I recently noticed this on another website and wrote a blog post on how it works. The jQuery example doesn't seem to actually modify what the user copies and pastes, it just adds a new context menu.
In short:
var content = document.getElementById("content");
content.addEventListener("copy", oncopy);
function oncopy() {
var newEl = document.createElement("p");
document.body.appendChild(newEl);
newEl.innerHTML = "In your copy, messing with your text!";
var selection = document.getSelection();
var range = selection.getRangeAt(0);
selection.selectAllChildren(newEl);
setTimeout(function() {
newEl.parentNode.removeChild(newEl);
selection.removeAllRanges();
selection.addRange(range);
}, 0)
}
The setTimeout at the end is important as it doesn't seem to work if the last part is executed immediately.
This example replaces your selected text at the last minute with my chosen string. You can also grab the existing selection and append whatever you like to the end.

Categories

Resources