I am trying to highlight/select the text from a huge text field. I was able to select the text using the below code, but it is selecting complete text. How do I select only the first few lines of the text.
cy.get('locator').first()
.trigger('mousedown')
.then(($el) => {
const el = $el[0]
const document = el.ownerDocument
const range = document.createRange()
range.selectNodeContents(el)
document.getSelection().removeAllRanges(range)
document.getSelection().addRange(range)
})
Related
I'm currently have a Google Sheet (Pushed to a website via PHP) with all my clients beer data. I'd like to take that data and copy it into a Google Doc Template for easy printing. In my example I can move the first row of data from the Sheet into the Doc but all the other rows from the sheet do not copy over.
I could use some help with the forEach statement, I'm thinking I need to parse the array and iterate through it in a different way than I'm currently attempting. (First time using Apps Script)
Here is what I've currently coded up.
function onOpen() {
const ui = SpreadsheetApp.getUi();
const menu = ui.createMenu('Print Menu');
menu.addItem('Create New Print Menu', 'createNewMenu')
menu.addToUi();
}
function createNewMenu() {
//Google Doc Template ID and Where to Save the New File
const googleDocTemplate = DriveApp.getFileById('1xzlvVOSW_LsgOrm2N2o1-FKYzfqp_2EAbhqrLTn53yk');
const destinationFolder = DriveApp.getFolderById('11HU0TvSPMMXUZaK5gTgg8jvofxTTt02j');
//Get all spreadsheet sheets and add values as 2D arrays.
const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Draft List');
const rows = sheet.getDataRange().getValues();
//Create date for new filename.
const dateData = new Date();
const curr_date = dateData.getDate();
const curr_month = dateData.getMonth() + 1; //Months are zero based
const curr_year = dateData.getFullYear();
const theDate = curr_year + "-" + curr_month + "-" + curr_date;
const newFileName = theDate + ' - Bar Print Menu';
//Using the row data in a template literal, we make a copy of our template document in our destinationFolder
const copy = googleDocTemplate.makeCopy(newFileName, destinationFolder)
//Once we have the copy, we then open it using the DocumentApp
const doc = DocumentApp.openById(copy.getId())
//All of the content lives in the body, so we get that for editing
const body = doc.getBody();
rows.forEach(function(rowData) {
//In these lines, we replace our template replacement tokens with values from our spreadsheet rows.
body.replaceText('{{onTapName}}', rowData[0]);
body.replaceText('{{onTapDescription}}', rowData[1]);
body.replaceText('{{onTapPrice}}', rowData[2]);
//Logger.log(rowData);
});
//We make our changes permanent by saving and closing the document
doc.saveAndClose();
}
This code will create a copy of the template file, copy the first row of data from Google Sheets and paste it into the template in the {{onTapName}}, {{onTapDescription}} & {{onTapPrice}} areas but the other rows from the Google Sheet do not copy over.
- Screenshot of Google Sheet, Google Doc Template and Result after running above code
If I uncomment out the "Logger.log(rowData);" line, I can see the code is going through each line of the data from the Google Sheet.
- Screenshot of Execution Log
How do I modify this forEach area to copy through each line of code into the template? I feel like I'm missing something very obvious here.
Thanks in advance for the help.
i am using ckeditor. i want to get last word when i press space and it will replace with a random word. i able able to get last word from the textarea and replace it with random word. but when i style a text (bold or italic) i am not able to get the exact cursor position. Because if my text is bold or italic and when i replace it with random word after replacement random word also bold or italic.
var r = editor.getSelection().getRanges()[0];
// var start = r.startOffset;
// var end = r.endOffset;
// r.collapse( 1 );
// r.setStartAt( ( r.startPath().block || r.startPath().blockLimit ).getFirst(), CKEDITOR.POSITION_AFTER_START );
// var docFr = r.cloneContents();
// var data = docFr.$.textContent
// var random = Math.floor(Math.random() * name.length);
// var randomword = (name[random]);
// var res =data.split(" ")
// var lastword = (res[res.length-1])
// text1 = text.substring(0,datalen-1) + randomword + text.substring(datalen+3, text.length);
The problem is in last line. I am not able to replace the word at exact position.
please help me out
This is a script I am writing to help me figure out how to write a more complex script.
In my spreadsheet, I have one column that contains a list of values ("testRange","testRangeValues"). I also have a dropdown list ("testCell","testCellValue"). The dropdown list contains some values that are in the "testRange" list and some that are not.
I would like my script to function in such a way that when I select a value from the dropdown list that matches value from the testRange list, the background color of the corresponding value in the testRange list changes to red.
function onEdit3(e) {
var testRange = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().getRange("A4:A8");
var testRangeValues = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().getRange("A4:A8").getValues();
var testCell = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().getRange("C4");
var testCellValue = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().getRange("C4").getValue();
for(var i = 0;i<testRange.length;i++){
if(testCellValue==testRangeValues[i]){
testRange[i].setBackground("Red");
}
}
}
Currently no color change is happening. I guess I'm not quite sure how to correctly write my for loop/if statement to achieve the intended effect. Is there perhaps a way to do this using just some sort of conditional formatting formula in my spreadsheet?
You want to change the background color of cell in the range of "A4:A8" that the value of dropdown list of "C4" is the same.
You want to achieve this using Google Apps Script.
From your script, you don't want to use the event object.
If my understanding is correct, how about this answer? Please think of this as just one of several possible answers.
Modification points:
The sheet object can be written by var sheet = SpreadsheetApp.getActiveSheet();. By this, you can use sheet for retrieving the range.
sheet.getRange("A4:A8") and sheet.getRange("C4") can be used one time.
In this case, the range object cannot be used in the loop, because testRange.length returns null.
When above points are reflected to your script, it becomes as follows.
Pattern 1:
In this pattern, only background color of the selected value is changed to the red color. So for example, when "A" is selected, the background color of "A" is changed to the red color. And when "C" is selected, the background color of "C" is changed to the red color. In this case, the background color of "A" is reset.
Modified script:
function onEdit3(e) {
var sheet = SpreadsheetApp.getActiveSheet();
var testRange = sheet.getRange("A4:A8");
var testRangeValues = testRange.getValues();
var testCell = sheet.getRange("C4");
var testCellValue = testCell.getValue();
var backgroundColors = testRangeValues.map(function([a]) {return [a == testCellValue ? "Red" : ""]});
testRange.setBackgrounds(backgroundColors);
}
Pattern 2:
In this pattern, the background color of the selected value is saved. So for example, when "A" is selected, the background color of "A" is changed to the red color. And when "C" is selected, the background color of "C" is changed to the red color. In this case, the background color of "A" is kept the red color.
Modified script:
function onEdit3(e) {
var sheet = SpreadsheetApp.getActiveSheet();
var testRange = sheet.getRange("A4:A8");
var testRangeValues = testRange.getValues();
var testCell = sheet.getRange("C4");
var testCellValue = testCell.getValue();
for (var i = 0; i < testRangeValues.length; i++) {
if (testRangeValues[i] == testCellValue) {
sheet.getRange("A" + (4 + i)).setBackground("Red");
break;
}
}
}
Modern javascript:
You can use modern javascript syntax. For this you need to enable V8 runtime. After this you can
/**
*
* #param {GoogleAppsScript.Events.SheetsOnEdit} e
*/
const onEdit = e => {
const sheet = e.range.getSheet();
const value = e.range.getValue();
if (sheet.getName() == 'Sheet1' && e.range.getA1Notation() === 'C2') {
const range = sheet.getRange(2, 1, sheet.getLastRow() - 1, 1);
range.setBackgrounds(
range.getValues().map(row => [row[0] === value ? 'red' : ''])
);
}
};
References:
setBackground(color)
setBackgrounds(color)
If I misunderstood your question and this was not the direction you want, I apologize.
I have an image saved in my Google drive called "logo.png".
I want to add the image to a Google document so that it's in the top left corner and so that it does not distort the text around it. (In other words, I want the text to "wrap" around the image).
How do I add an image to a Google Doc using Google Script so that surrounding text wraps around the image?
My script so far:
function myFunction(e) {
var t1 = 'Center for Success';
var t2 = 'Foundational Hall';
var t3 = 'Instruction Sheet for Testing Requirements';
var boldRight ={};
boldRight[DocumentApp.Attribute.BOLD]=true;
boldRight[DocumentApp.Attribute.HORIZONTAL_ALIGNMENT]=DocumentApp.HorizontalAlignment.RIGHT;
var boldCenterUnderline ={};
boldCenterUnderline[DocumentApp.Attribute.BOLD]=true;
boldCenterUnderline[DocumentApp.Attribute.UNDERLINE]=true;
boldCenterUnderline[DocumentApp.Attribute.HORIZONTAL_ALIGNMENT]=DocumentApp.HorizontalAlignment.CENTER;
var filename = 'fileTest';
var doc = DocumentApp.create(filename);
var body = doc.getBody();
body.appendParagraph(t1).setAttributes(boldRight);
body.appendParagraph(t2).setAttributes(boldRight);
body.appendParagraph(space);
body.appendParagraph(t3).setAttributes(boldCenterUnderline);
doc.saveAndClose();
}
Desired Result:
I saw here that an image can be added in various ways, but neither approach has worked for me AND I do not see how I can control a wrapping attribute.
Update
I tried using the following code (with fake ID shown in URL), but it just created a blank document:
var image = "https://drive.google.com/open?id=2PJGK5C64HLKKoQIv52jGhUjjdiXU34Mp";
var fileID = image.match(/[\w\_\-]{25,}/).toString();
var blob = DriveApp.getFileById(fileID).getBlob();
body.appendImage(blob)
Kendo UI 2015.2.805 Kendo UI Editor for Jacascript
I want to extend the kendo ui editor by adding a custom tool that will convert a user selected block that spans two or more paragraphs into block of single spaced text. This can be done by locating all interior p tags and converting them into br tags, taking care not to change the first or last tag.
My problem is working with the range object.
Getting the range is easy:
var range = editor.getRange();
The range object has a start and end container, and a start and end offset (within that container). I can access the text (without markup)
console.log(range.toString());
Oddly, other examples I have seen, including working examples, show that
console.log(range);
will dump the text, however that does not work in my project, I just get the word 'Range', which is the type of the object. This concerns me.
However, all I really need however is a start and end offset in the editor's markup (editor.value()) then I can locate and change the p's to br's.
I've read the telerik documentation and the referenced quirksmode site's explanation of html ranges, and while informative nothing shows how to locate the range withing the text (which seems pretty basic to me).
I suspect I'm overlooking something simple.
Given a range object how can I locate the start and end offset within the editor's content?
EDIT: After additional research it appears much more complex than I anticipated. It seems I must deal with the range and/or selection objects rather than directly with the editor content. Smarter minds than I came up with the range object for reasons I cannot fathom.
Here is what I have so far:
var range = letterEditor.editor.getRange();
var divSelection;
divSelection = range.cloneRange();
//cloning may be needless extra work...
//here manipulate the divSelection to how I want it.
//divSeletion is a range, not sure how to manipulate it
var sel = letterEditor.editor.getSelection()
sel.removeAllRanges();
sel.addRange(divSelection);
EDIT 2:
Based on Tim Down's Solution I came up with this simple test:
var html;
var sel = letterEditor.editor.getSelection();
if (sel.rangeCount) {
var container = document.createElement("div");
for (var i = 0, len = sel.rangeCount; i < len; ++i) {
container.appendChild(sel.getRangeAt(i).cloneContents());
}
html = container.innerHTML;
}
html = html.replace("</p><p>", "<br/>")
var range = letterEditor.editor.getRange();
range.deleteContents();
var div = document.createElement("div");
div.innerHTML = html;
var frag = document.createDocumentFragment(), child;
while ((child = div.firstChild)) {
frag.appendChild(child);
}
range.insertNode(frag);
The first part, getting the html selection works fine, the second part also works however the editor inserts tags around all lines so the result is incorrect; extra lines including fragments of the selection.
The editor supports a view html popup which shows the editor content as html and it allows for editing the html. If I change the targeted p tags to br's I get the desired result. (The editor does support br as a default line feed vs p, but I want p's most of the time). That I can edit the html with the html viewer tool lets me know this is possible, I just need identify the selection start and end in the editor content, then a simple textual replacement via regex on the editor value would do the trick.
Edit 3:
Poking around kendo.all.max.js I discovered that pressing shift+enter creates a br instead of a p tag for the line feed. I was going to extend it to do just that as a workaround for the single-space tool. I would still like a solution to this if anyone knows, but for now I will instruct users to shift-enter for single spaced blocks of text.
This will accomplish it. Uses Tim Down's code to get html. RegEx could probably be made more efficient. 'Trick' is using split = false in insertHtml.
var sel = letterEditor.editor.getSelection();
if (sel.rangeCount) {
var container = document.createElement("div");
for (var i = 0, len = sel.rangeCount; i < len; ++i) {
container.appendChild(sel.getRangeAt(i).cloneContents());
}
var block = container.innerHTML;
var rgx = new RegExp(/<br class="k-br">/gi);
block = block.replace(rgx, "");
rgx = new RegExp(/<\/p><p>/gi);
block = block.replace(rgx, "<br/>");
rgx = new RegExp(/<\/p>|<p>/gi);
block = block.replace(rgx, "");
letterEditor.editor.exec("insertHtml", { html: block, split: false });
}