Does anyone know a fast way to copy multiple elements from an inspect page?
What I mean by that is I have a number of elements with same qualities i.e. same class and I want to copy all of them to my clipboard. Is there a way within inspect tool to do such a "trick" ? :)
Thank you in advance!
There's no specific simple way to do this, you can only using code to extract the elements you want.
For example if you want to get elements with the same class name, you can use the following code:
var outputText = "";
var targets = document.getElementsByClassName('classname');
for( var i = 0; i < targets.length; i++ ) {
outputText += targets[i].outerHTML;
}
console.log(outputText);
Then you can copy the output in the console.
Related
So I've been working through a problem of pulling structured data from a spreadsheet and them using App Script to insert it into a Template Google Doc.
I have it working simply as concatenated strings, but I'm trying to do it with the BODY class so if I want to put the end product into Gmail it could be easier. Or if I want to retain table structure....
So, everything is fine and dandy, except for this one bit of code. I'm struggling with setBold. It's a weird syntax in that it's a boolean operation, right?
So here is what I have and it's pretty easy to grok I think:
for(var i = 0; i < num; i++) {
var songName = String(dataArray[i][1]);
var sWs = String(dataArray[i][2]);
var pub = String(dataArray[i][3]);
newText.editAsText().appendText('SONG NAME:'+ nLi).setBold(true);
newText.editAsText().appendText(songName + brk).setBold(false);
newText.editAsText().appendText('SONGWRITER(S):' + nLi);
But it's coming out as:
SONG NAME:
I have also tried this code:
newText.editAsText().setBold(true);
newText.editAsText().appendText('SONG NAME:'+ nLi);
newText.editAsText().setBold(true);
newText.editAsText().appendText(songName + brk);
newText.editAsText().appendText('SONGWRITER(S):' + nLi);
Thinking of the setBold as setting then unsetting a flag.
Neither worked.
I prefer using styles:
function addboldtext() {
const doc=DocumentApp.getActiveDocument();
const body=doc.getBody();
const style1={};
style1[DocumentApp.Attribute.BOLD]=true;
style1[DocumentApp.Attribute.FOREGROUND_COLOR]='#000000';//you can add all of the attributes that you wish
body.appendParagraph("This is text").setAttributes(style1)
}
In looking at this image you can see in an ideal world each box would have the same height of content in each box. However in the real world we can't control how many characters the client uses for a heading. Wondering thoughts on how to deal with a situation like this? Is it ok to just let it be as is?
This will create an array of heights of an element by class, then find the tallest, and then make them all that height.
<script>
var headerHeights = [];
var mclength = document.getElementsByClassName("myClass").length;
for (i = 0; i < mclength; i++) {
headerHeights[i] = document.getElementsByClassName("myClass")[i].getBoundingClientRect().height;
}
var headerMaxHeight = Math.max(...headerHeights);
for (i = 0; i < mclength; i++) {
document.getElementsByClassName("myClass")[i].style.height = headerMaxHeight+"px";
}
</script>
You will likely want to make this a function which replaces "myClass" with a function parameter so that you can call it for each class you add. You will also want to add a listener for when a person resizes their window to rerun the function.
I have an application that is having issue when populating selects with over 100 items. This problem only occurs in IE8. I am using angularjs to do the population, but my research shows that this is a general problem with IE8. What solutions have others used to deal with this problem. We have over 40,000 users tied to IE8 for the foreseeable future (Fortune 200 company) so moving to another browser is not an option.
Some thoughts I had.
Create a series of option tags as a one long string in memory and replace the innerHTML of the . But running some people samples this does not appear to solve the issue.
Originally populating the select with a few and then adding the rest as the user scrolls down. I am not sure if this is possible, or how to implement this
I am sure others have run into this issue. Does anyone have some ideas?
Thanks,
Jerry
Another solution that preserves the original <select> is to set the <option> values after adding the options to the <select>.
Theory
Add the <option> elements to a document fragment.
Add the document fragment to the <select>.
Set the value for each <option>.
Practice
In practice we end up with a couple issues we have to work around to get this to work:
IE11 is very slow when setting the value for each individual <option>.
IE8 has selection bugs because it isn't properly doing a re-flow/layout on the <select>.
Result
To handle these what we really do is something like the following:
Add the <option> tags to a document fragment. Make sure to set the values so that step 3 is a no-op in IE11.
Add the document fragment to the <select>.
Set the value for each <option>. In IE8 this will set the values, in IE11 this is a no-op.
In a setTimeout add and remove a dummy <option>. This forces a re-flow.
Code
function setSelectOptions(select, options)
{
select.innerHTML = ''; // Blank the list.
// 1. Add the options to a document fragment.
var docFrag = document.createDocumentFragement();
for (var i = 0; i < options.length; i++)
{
var opt = document.createElement('option');
opt.text = options[i];
docFrag.appendChild(opt);
}
// 2. Add the document fragment to the select.
select.appendChild(docFrag);
// 3. Set the option values for IE8. This is a no-op in IE11.
for (i = 0; i < options.length; i++)
select.options[i].text = options[i];
// 4. Force a re-flow/layout to fix IE8 selection bugs.
window.setTimeout(function()
{
select.add(document.createElement('option'));
select.remove(select.options.length - 1);
}, 0);
}
The best solution seems to be to create the Select and it's options as a text string and add that string as the innerHTML of the containing tag such as a DIV. Below is some code.
<div id="selectHome" ></div>
In JS (from angular controller)
function insertSelect(divForSelect) {
var str = "<select id='myselect'>";
for (var i = 0; i < data.length; i++) {
str += '<option>' + data[i] + '</data>';
}
str += '</select>';
divForSelect.innnerHTML = str;
}
Note that inserting options into a existing Select is very slow (8,000 msecs for 2000 items). But, if the select and the options are inserted as a single string it is very fast (12 msec for 2000 items).
I am trying to use Google Apps Script to replace text into a Docs template and save it as a .pdf. I am mostly successful, but I am having one problem. I'd like for the script to search for a text in the template, replace the text with provided text, using bullets. It will ignore any extra \n that may have been placed into the text. Here is an example text:
Today was a good day.
Tomorrow will be a good day.
Yesterday was a decent day.
In my document, I would like the text to replace _text_ in a line: Comments: _text_. Ultimately, what should print out is the following:
Comments:
- Today was a good day.
- Tomorrow will be a good day.
- Yesteday was a decent day.
This is the code that I have so far, but it is not working too well. If anyone could offer any help, it would be greatly appreciated.
var listr = "";
var trunc = text.split("\n"); \\ where text is to be placed into the template
var index = b.findText("_text_").getStartOffset(); \\ var b is getBody()
for (var j = (trunc.length - 1); j >= 0; j--)
if(!trunc[j].equals("")) b.insertListItem(index, trunc[j]);
b.replaceText("_text_", "");
Any help would be much appreciated. I am having the hardest time understanding the concept of the indexes in Google Docs. Thank you.
Hello. Just wanted to let you know how I have ended up implementing this:
var trunc = text.split("\n"); \\where text is to be placed into the template
var index = b.getChildIndex(b.findText("foo").getElement().getParent()) + 1;
for (var j = (trunc.length - 1); j >= 0; j--)
if (trunc[j] != "") b.insertListItem(index, trunc[j]);
Hope that helps. It pushes the elements back on to each other backwards.
Ok well this crude code seems to insert at the beginning of the PARAGRAPH containing the TEXT, which appears to be a separate child element. Probably this particular code will only work if the text is not inside a sub-table, sub-list, etc... but maybe it will help.
var element = DocumentApp.create('newDoc').getBody()
.appendListItem('testing').copy();
var index = b.getChildIndex(
b.findText('_text_').getElement().getParent().asParagraph() );
b.insertListItem(index, element);
I've had a long day maybe I can improve it later, mostly what I think was missing was the getChildIndex() function. Also using the newDoc the insertListItem() had some weird "Element must be detached." message until I used .copy() so mental note there.
I have a well formatted HTML table (the HTML text is generated by a reporting tool) and I want to turn it into a "programmable" table in GWT.
I need to show that content as it is provided, but I also need to inspect the DOM, get the tables, and add ClickHandler's to the rows and cells.
I am able to do something similar with images:
Html html = new HTML(htmlText);
ImageElement domElement = getChildImageByTagAndId(html.getElement(), "img", "blah");
Image image = Image.wrap(domElement);
image.addClickHandler(...);
My question is: What is the correct way to do this with tables?
I could not find a wrap() method for <table>, <tr>, and <td> elements.
Note: this question was asked (and not answered) in the comments in the accepted answer here.
I am unaware of an easy way to wrap an existing Table with the sub tr and td elements.
Given the constraint that you are relying on a third party tool, I recommend trying to build a custom table parser which will parse the existing table, build a FlexTable, and then replace the existing table with the new FlexTable.
As ugly as this is, I am not sure there is a better way...
It may depend on how exactly the table is setup, but you may try playing around with something like the below example to go through the existing table and use the getNodeValue() to build the content of the FlexTable....
Element table = DOM.getElementById("someTableId");
int numTopNodes = table.getChildNodes().getLength();
for(int topNode = 0; topNode < numTopNodes; topNode++){
Node top = table.getChildNodes().getItem(topNode);
System.out.println("Top Node: "+top);
for(int subNode = 0; subNode < top.getChildCount(); subNode ++){
Node sub = top.getChildNodes().getItem(subNode);
System.out.println("Sub Node: "+sub);
for(int rows = 0; rows < sub.getChildCount(); rows ++){
Node row = sub.getChildNodes().getItem(rows);
System.out.println("Row: "+row);
for(int cells = 0; cells < row.getChildCount(); cells++ ){
Node cell = row.getChildNodes().getItem(cells);
System.out.println("CELL: "+cell.getNodeValue()); // use value to build to build a new FlexTable
}
}
}
}