I am trying to create a copy image functionality using the following code:
// Code goes here
function CopyImageById(Id)
{
const imgs = document.createElement('img');
imgs.src = document.getElementById(Id).src;
//alert ('Create image') ;
const bodys = document.body ;
bodys.appendChild(imgs);
//alert ('Image on document')
let myrange;
if (document.createRange)
{
//alert ('CreateRange work');
myrange = document.createRange();
myrange.setStartBefore(imgs);
myrange.setEndAfter(imgs);
myrange.selectNode(imgs);
}
else
{
alert ('CreateRange not working');
}
const sel = window.getSelection();
sel.addRange(myrange);
const successful = document.execCommand('copy');
const msg = successful ? 'successful' : 'unsuccessful';
//alert('Copy image command was ' + msg);
bodys.removeChild(imgs);
document.getElementById('answer').innerHTML="Copy image command was " + msg ;
}
Reproducer: http://jsfiddle.net/xz14jp3f/
The copied image however is only pasting on word document such as google doc, but not on all the places such slack or stackoverflow. If you copy the image using the chrome's right click context menu option to copy the image, we can paste it everywhere.
How can I fix this?
Related
I need an Adobe Script that do this:
Select TextFrame with the whole Text Script (page1, text, page2, text and so on);
Cut a paragraph (usually separated by a \r or ^p);
User selects or create a new TextFrame;
Paste the line cut before on the new empty TextFrame; and
Go to the next paragraph.
I've been doing this typesetting job and I came across this Typesetterer for Photoshop, went on a journey to find a similar script/application for inDesign and I found this this solution, tried it and worked, boosting my productivity by at least 2x. Tried this split one but it takes way longer to resize and move all the generated TextFrames. But it was really useful in developing my final code.
The main problem with this approach is that it required the typesetting script to be in a .txt file, which breaks all Bold and Italic from the original script.
main();
function main() { // Main() just to keep it organized
try {
var myMeasuringUnit = app.scriptPreferences.measurementUnit;
app.scriptPreferences.measurementUnit = MeasurementUnits.POINTS;
} catch (exception) {
alert(exception.description);
exit();
}
var myTextFrameSelection = app.activeDocument.selection;
cutAndPaste(myTextFrameSelection);
try {
app.scriptPreferences.measurementUnit = myMeasuringUnit;
} catch (exception) {}
}
function cutAndPaste(myTextFrameSelection) {
for (elementsInSelection = 0; elementsInSelection < myTextFrameSelection.length; elementsInSelection++) {
if (myTextFrameSelection[elementsInSelection].constructor.name == "TextFrame") {
var myParagraphs = myTextFrameSelection[elementsInSelection].texts[0].paragraphs;
var isCopied = true;
for (var i = 0; i < myParagraphs.length; i++) {
try {
myParagraphs[i].insertionPoints.itemByRange(0, -2).select();
app.cut();
isCopied = true;
} catch (exception) {
isCopied = false;
}
if (isCopied) {
/*
Attempt at adding a way to select another TextFrame and app.paste() the previously app.cut() line in it
var doc = app.activeDocument.selection[0];
doc.addEventListener('afterSelectionChanged', selectionChanged);
function selectionChanged() {
if (doc.selection[0] instanceof TextFrame && doc.selection[0].contents == '' && doc.selection[1] == null) {
if (doc.selection[0] instanceof TextFrame) {
doc.selection[0].contents = app.paste();
}
}
*/
app.paste(); // This just pastes it in the same folder
}
}
}
}
} // For now, what it does it "cut paragraph from the TextFrame but also paste in the same TextFrame"
So far, it just cut from the TextFrame, paragraph after paragraph, and it pastes on the same TextFrame. It's close to doing what I need, but I can't seem to find a way to select a new Frame while in the main loop. I commented out the possible solution that I'm struggling to get to work.
Maybe I'm using the wrong cut/paste functions too? Maybe it is easier to modify the 2nd link solution to accept .docx?
Important difference between RisingFog's solution and Eugeny Budantsev solition is the interaction with user. Former script shows the dialog window and keep it running until you close the window. Later runs just once and can't keep tracking user manipulations.
So if you want to keep your script running (and doing something as reaction on user manipulations) you need to show a some window even if the window will be empty. Something like this:
#targetengine session
var dialog = new Window("palette", undefined, undefined);
dialog.preferredSize.width = 200;
dialog.preferredSize.height = 50;
dialog.text = "Select next frame";
dialog.onClose = function() {
doc.removeEventListener('afterSelectionChanged', selectionChanged);
}
dialog.show();
var doc = app.activeDocument;
doc.addEventListener('afterSelectionChanged', selectionChanged);
function selectionChanged() {
// here is the code that will run wenever you change selection
if (doc.selection[0] instanceof TextFrame
&& doc.selection[0].contents == ''
&& doc.selection[1] == null) {
alert('Next empty text frame is selected!')
}
}
Of course you can fill the window with some texts or buttons.
Update
Here is the example how you can cut first paragraph from selected non-empty text frame (suppose it's the Text Script) and paste this paragraph automatically into next selected empty frame:
#targetengine session
var dialog = new Window("palette", undefined, undefined);
dialog.preferredSize.width = 300;
dialog.preferredSize.height = 50;
dialog.text = "Please, select next frame";
dialog.onClose = function() {
doc.removeEventListener('afterSelectionChanged', selectionChanged);
}
dialog.add("statictext", undefined, "Last cutted text:");
var msg = dialog.add("edittext");
msg.text = "";
msg.characters = 40
dialog.show();
var doc = app.activeDocument;
doc.addEventListener('afterSelectionChanged', selectionChanged);
function selectionChanged() {
var sel = doc.selection[0];
if (sel instanceof InsertionPoint) sel = sel.parent.textContainers[0];
if (sel instanceof TextFrame || sel instanceof Story) {
if (sel.contents != '') {
app.select(sel.paragraphs[0], SelectionOptions.REPLACE_WITH);
msg.text = sel.paragraphs[0].contents;
app.cut();
app.selection = null;
}
else {
sel.texts.everyItem().select();
app.paste();
app.selection = null;
// remove '\r' at the very end of text in the frame
app.findGrepPreferences.findWhat ="\r$";
app.changeGrepPreferences.changeTo = "";
sel.changeGrep();
}
}
}
Update 2
Here is the same script. Only difference, you don't need click on Text Script frame anymore. You need select the text frame before you run the script and then the script will cut first paragraph from this frame automatically every time when you click on any empty text frame.
#targetengine session
var dialog = new Window("palette", undefined, undefined);
dialog.preferredSize.width = 300;
dialog.preferredSize.height = 50;
dialog.text = "Please, select next frame";
dialog.onClose = function() {doc.removeEventListener('afterSelectionChanged', selectionChanged)}
dialog.add("statictext", undefined, "Last copied text:");
var msg = dialog.add("edittext");
msg.text = "";
msg.characters = 40;
// --- here is the Pause button
var pause = false;
var pause_btn = dialog.add("button", [10,10,300,30], "Pause");
pause_btn.onClick = function() {
pause = !pause;
// if (pause) msg.text = "[PAUSED] " + msg.text; // it can be done better, but it works, too
// if (!pause) msg.text = msg.text.replace(/^\[PAUSED\] /, "");
pause_btn.text = pause ? "Resume" : "Pause"; // this is way better
};
// ---
var doc = app.activeDocument;
var master_frame = app.selection[0]; // <-- the Text Script frame
if (master_frame instanceof TextFrame || master_frame instanceof Story) {
dialog.show();
app.selection = null;
doc.addEventListener('afterSelectionChanged', selectionChanged);
} else {
alert("Please, select a frame with text before run the script!");
exit();
}
function selectionChanged() {
if (pause) return; // <-- here you check the state of the button
var sel = doc.selection[0];
if (sel instanceof InsertionPoint) sel = sel.parent.textContainers[0];
if (sel instanceof TextFrame || sel instanceof Story) {
if (sel.contents == '' && master_frame.contents != '') {
app.select(master_frame.paragraphs[0], SelectionOptions.REPLACE_WITH);
msg.text = master_frame.paragraphs[0].contents;
app.cut();
app.selection = null;
sel.texts.everyItem().select();
app.paste();
app.selection = null;
// remove '\r' at the end
app.findGrepPreferences.findWhat ="\r$";
app.changeGrepPreferences.changeTo = "";
sel.changeGrep();
}
if (master_frame.contents == '') alert ("No text to paste anymore!")
}
}
I've added 'Pause' button to the window.
I have the following code for chrome addon's js to copy some certain data to clipboard from a certain webpage(I will write code to get data from the webpage later).
// 1. Create the button
var testButton = document.createElement("button");
testButton.innerHTML = "Copy";
// 2. Append somewhere
var btnPos = document.getElementsByClassName("menu-userdetails")[0];
btnPos.appendChild(testButton);
// 3. Add event handler
testButton.addEventListener ("click", copyToClipboard);
function copyToClipboard() {
var textArea = document.createElement("textarea");
textArea.value = "test copying";
btnPos.appendChild(textArea);
textArea.select();
try {
var successful = document.execCommand('copy');
var msg = successful ? 'successful' : 'unsuccessful';
console.log('Copying text command was ' + msg);
} catch (err) {
console.log('Oops, unable to copy');
}
document.body.removeChild(textArea);
}
In this code I have to append the text area to the webpage(after button click) before copying it. But I don't want the textarea to be shown I want to just copy the data inside the textarea without displaying the textarea.
textArea.style.height = "0px";
textArea.style.width = "0px";
textArea.style.opacity = "0";
Adding this code hides the text area.
But even better solution was already in my code, I just made a little mistake in it.
I wrote
document.body.removeChild(textArea);
While actually I had to write
btnPos.removeChild(textArea);
this removes the text area after copying and its so fast that you can't even see the text area appear and disappear.
I'm doing this in background script:
var link = document.createElement('div');
Then link is null. I guess it's because extensions background page have no DOM, or am i have no access to it?
Anyway i'm need this to make copy to clipboard. Here part where i'm try to use it:
function selectionOnClick(info, tab) {
var link = document.createElement('div');
var range = document.createRange();
link.innerHTML = ShortURL(info.selectionText);
range.selectNode(link);
window.getSelection().addRange(range);
try {
var successful = document.execCommand('copy');
if (!successful) {
alert("Your browser doesn't support copy to clipboard.");
}
} catch(err) {
alert("Your browser doesn't support copy to clipboard.");
}
window.getSelection().removeAllRanges();
link.parentNode.removeChild(link);
}
chrome.contextMenus.create({'title': 'Short selected', 'contexts':['selection'], 'onclick':selectionOnClick});
You have created the node but have not append it to anything. Append it to body:
document.getElementsByTagName('body').appendChild(link);
just make the "link" variable global then initialize it inside the function..
var link = null;
function selectionOnClick(info, tab) {
link = document.createElement('div');
.
.
.
I am designing an chrome extension for Gmail. In this I want to get selected/highlighted text. I tried following code:
if (!window.x) {
x = {};
}
x.Selector = {};
x.Selector.getSelected = function() {
var t = '';
if($('.compose-container').getSelection){
t = $('.compose-container').getSelection();
alert(t);
} else if (window.getSelection) {
t = window.getSelection();
} else if (document.getSelection) {
t = document.getSelection();
} else if (document.selection) {
t = document.selection.createRange().text;
}
return t;
}
It is not giving me selected text in compose mail.
Please help me out.
You would need to use the copy command to achieve this.
var copyText = document.execCommand('copy');
Basically it will copy any text selection in the browser.
You can check out this link on how it was fully utilized
As per gRenzFries answer, I code same as link provided by him. But slight addition in code to paste it in textbox.
Code to Copy text :
var emailLink = document.querySelector('.gmail_default');
var range = document.createRange();
range.selectNode(emailLink);
window.getSelection().addRange(range);
try {
// Now that we've selected the anchor text, execute the copy command
var successful = document.execCommand('copy', true);
} catch(err) {
}
Code to paste it in textbox:
$('#text-to-display').val(""); //reset textbox value
$('#text-to-display').focus(); //set focus to textbox
document.execCommand("Paste");
This code works just as expected.
Using a sidebar, I get user input and save it as a script property. Next time the sidebar is loaded, I'd like to check if the saved property exists. If so, display it instead of the text entry box.
I know to use:
google.script.run.withSuccessHandler().myFunction()
Honestly, I have tried so many different things at this point. Any help would be greatly appreciated.
This is what I have tried, I want to load values in the sidebar if they exist. If they do not I want it load a text entry box, that is what it does by default.
Edit - Adding Code
function loadSidebarValues() {
if (dateText != 'ErrorStuff') {
var div = document.getElementById('dateValue');
div.innerHTML = dateText;
var errorDiv = document.getElementById('error');
errorDiv.innerHTML = "";
$('#dateText').val(
PropertiesService.getScriptProperties().getProperty('dateColumn')
);
} else {
var div = document.getElementById('sidebarValues');
div.innerHTML = "";
var errorDiv = document.getElementById('error');
errorDiv.innerHTML = 'There was an error.';
}
var scriptProperties = PropertiesService.getScriptProperties();
scriptProperties.setProperties({
'dateColumn': 'dateText',
});
Logger.log("date: " + userProperties.getProperty('dateColumn'));
}
function onLoad(){
if (PropertiesService.getScriptProperties().getProperty('dateColumn') != null) {
loadSidebarValues();
};
}
You can write server code to retrieve UserProperties value, then run the HTML script to get that value as instructed in File-open dialogs
section in this guide
What they do:
getOAuthToken in Code.gs
Call that function in Picker.html by this code:
function getOAuthToken() {
google.script.run.withSuccessHandler(createPicker)
.withFailureHandler(showError).getOAuthToken();
}
createPicker method from withSuccessHandler take token value from getOAuthToken in first step.
You can use the same pattern for your own case.