DocumentApp Script - Merge cell not working - javascript

cell.appendTable([["Hello"],["Hello","I","J"]])
Outputs to:
|Hello|
|Hello|I |J |
I want to merge the first row.
Developed in scripts.google.com DocumentApp. - With Table And Cell Element

If you were expecting to have a merged cell that, like what you can do in a spreadsheet, that is not possible. Simply because that's not possible in Google Documents (at least not yet). Therefore the API cannot do this (it can only do things that are also possible manually).
Try merge() function : Merges the element with the preceding sibling of the same type.
Only elements of the same ElementType may be merged. Any child
elements contained in the current element are moved to the preceding
sibling element.
The current element is removed from the document.
var body = DocumentApp.getActiveDocument().getBody();
// Append two paragraphs to the document.
var par1 = body.appendParagraph('Paragraph 1.');
var par2 = body.appendParagraph('Paragraph 2.');
// Merge the newly added paragraphs into a single paragraph.
par2.merge();
Reference

Found Answer.
Merge Cell Functionality didn't supported by Google App Script yet.

Related

How to get all possible valid attributes on a DOM element [duplicate]

This question already has answers here:
How to list all element attributes in JS?
(3 answers)
Closed 5 years ago.
Please note that .attributes only gets the current attributes, which is not what this question is about.
I want a way to get all the attributes of a DOM element. Not just the ones that are on it now, but the ones that are possible in the future too.
The specific use case is to find the potential attributes in an SVGElement that aren't in an HTMLElement - there's a list on MDN (SVG Attribute reference), but, for obvious reasons, hardcoding is not a good idea.
My initial thought was to iterate through the prototype chain of an instance of each and compare the two lists (with basic filtering for event handlers), but this doesn't actually give the potential svg attributes.
EDIT
IMPORTANT NOTE - pasting your answer code into the console on this page and using document.body as a target should show a list of over 50 attributes, including things like contentEditable, contextMenu, dir, style, etc.
This also needs to work cross-browser.
Could something like this be what you're looking for?
It looks like a DOM element object stores empty keys for all possible attributes. Could you loop over these keys and store them in an array, then from there use something similar to filter out inherited attributes?
HTML
<svg id="blah"></svg>
Javascript
const blah = document.getElementById('blah')
let possibleKeys = []
for (let key in blah) {
possibleKeys.push(key)
}
Here's a JSBin example ... it looks like it produces a list of all possible attributes but it would need some filtering.
See also this thread.
How to list all element attributes in JS?
Any one of these should work because they return a live HTMLCollection.
var svgElement = window.document.getElementsByClassName("someSvgClass")[0];
//assume someSvgClass is on svg element.
//var svgElement = window.document.getElementsByTagName("svg")[0];
//var svgElement = window.document.getElementsByName("mySvg")[0];
//assume svg has this name.
var svgAttributes = svgElement.attributes;
for(let i=0; i<svgAttributes.length; i++) {
console.log(svgAttributes[i]);
}
See the below documentation from MDN on getElementsByTagName()
The Element.getElementsByTagName() method returns a live
HTMLCollection of elements with the given tag name. The subtree
underneath the specified element is searched, excluding the element
itself. The returned list is live, meaning that it updates itself with
the DOM tree automatically. Consequently, there is no need to call
several times Element.getElementsByTagName() with the same element and
arguments.
The documentation for getElementsByName , and getElementsByClassName say the same thing; a live node list is returned. If you'd like to try it, I created a fiddle here.
You'll see that svgAttributes list is automatically updated upon clicking "Add Attribute" without re-executing any of those functions.
There is no API for that and I don't think a workaround is possible because when you change an attribute on a current DOM node, the browser is responsible for re-rendering and updating the webpage in a low-level way that is not exposed to the JavaScript context.
Also, keep in mind that any correctly formatted attribute is actually valid in the context of a DOM tree, even though it might not trigger any change at the rendering level or in the way the browser renders the page. Especially the data-* attributes.
There might be some vendor-specific API but that wouldn't be useful if you want cross-browser compatibility.
You need to hardcode it, sadly. Given that you specifically want the SVGElement attributes, maybe you can scrape the W3's SVG standard document to automatically create the list?
Edit: I made a snippet to easily scrape the values from the standard:
const uniq = arr => Array.from(new Set(arr))
const nameElements = document.querySelectorAll('table[summary="Alphabetic list of attributes"] .attr-name')
const arrNameElements = Array.prototype.slice.call(nameElements)
const svgAttributes = uniq(arrNameElements.map(el => el.innerText.replace(/\‘|\’/g, '')))
Just execute it on the svg attributes page, by opening the dev console on the page and pasting in this code :)
Edit 2: I forgot the presentation attributes. I'll let you figure that one out ;)

How to create shallow copy of element?

Recently in this question I asked how to find out if style is present in a class. I was told (by skobaljic) that I need to clone element. During the call .clone() of the element (jQuery method) the resulting object contains default styles (e.g. from style sheet) so the inserted styles are not included in the clone. This is how I understood it. But it seems to be strange to clone complete element including all his childern elements which may be hunderets or thousands when I need to detect if 6 style are present. I cheched the jQuery's code for clone method. There is this:
destElements = getAll( clone );
srcElements = getAll( elem );
So the function getAll is called twice.
Then I checked what contains getAll:
var ret = typeof context.getElementsByTagName !== "undefined" ?
context.getElementsByTagName( tag || "*" ) :
typeof context.querySelectorAll !== "undefined" ?
context.querySelectorAll( tag || "*" ) :
[];
From Mozilla manual:
The Element.getElementsByTagName() method returns a live
HTMLCollection of elements with the given tag name. The subtree
underneath the specified element is searched, excluding the element
itself.
Document.querySelectorAll() - Returns a list of the elements within
the document (using depth-first pre-order traversal of the document's
nodes) that match the specified group of selectors. The object
returned is a NodeList.
So it is evident that creating deep copy of the element is pointless and it takes performance. This problem is yet intensified when I need to make deep search/comparison which would lead to excessive waste of resources. I would like to clone the element without it's children element. Is this possible? The clone should contain the default styles just like you do it with .clone(). How to do it?
i believe this can help you:
Source: http://www.w3schools.com/jsref/met_node_clonenode.asp
// Copy the element and its child nodes
var clone_with_child = yourElement.cloneNode(true);
// Copy only the element
var clone_without_child = yourElement.cloneNode(false);

Add an HTML class to a DOM element controlled by two.js

I'm trying to add a class and ID to specific Two.js objects in this project: http://itpblog.evejweinberg.com/Homework/Open/ (click a few times to play)
If I console.log the word 'background' I see that these are two.js objects but I can't seem to use css or jquery to add a class/ID to them.
Any help is appreciated!
I even tried adding it to the whole project but that did not work:
$(document.body).addClass("dropshadow");
two.js entities are not DOM elements themselves, but each Scene, Group, or Polygon contains at least one reference to the DOM element that gets drawn when the entity is changed. To reference various DOM elements use the following syntaxes:
// Initialize two.js and attach to a dom element referenced by `canvas`
var two = new Two(params).appendTo(canvas);
// Two.Scene
var my_scene = two.renderer.domElement;
// Two.Group
var my_group = document.getElementById(two.scene.id);
// Two.Polygon — requires knowing the ID by means of your custom app logic.
var my_poly = document.getElementById(my_poly_html_id);
my_poly.classList.add('my-class');
Here's a screenshot showing all three commands in an actual app along with the outcome of each, with one additional command add a class to the shape that was targeted. The syntax of the last command differs but I omitted the var statements so that the console would display the result instead of outputting undefined.
If you'd like to create custom HTML IDs for individual shapes, use the .id setter before the initial render of your shape. Since most of this code is just setup, I offer a practical example on one of my own projects. In that snippet, a shape variable holds a new instance of Two.Polygon so calling shape.id = 'something-unique' before calling two.update() to draw the shape for the first time results in a DOM element with a custom HTML ID. Here is an incomplete block of setup code showing how to set the ID:
// Create new shape
var shape = two.makeRectangle(START_X, START_Y, START_WIDTH, START_HEIGHT);
// Set custom ID
shape.id = 'shape-' + Math.random(10000000);
// Draw shape for first time.
two.update();

How to apply css styles to dynamic JavaScript array?

I'm trying to apply CSS styles to input elements that are added to the HTML DOM dynamically via a JSON object.
Essentially an Ajax call receives a JSON payload with an array of data. Some KnockoutJS code then foreach's over the DOM to dynamically add rows.
I'm trying to add styles to inputs where a value is less than a required value. The bottom line is, I know the elements are dynamic to the DOM, and I'm having trouble accessing them so I can apply the style. I've tried both jQuery and pure JavaScript, and I can't access the newly added fields.
How would I do this?
I have a very complex fiddle created that creates the inputs. But I can't figure out how to style those inputs whose values are less than the current year.
I'm trying to add the .k-invalid style to the NextPaymentDate input whose value is less than the current year.
var $incomeWrapper = $("#income-wrapper");
$incomeWrapper.find("input#iNextPaymentDate_" + i).removeClass("k-valid").addClass("k-invalid");
The above doesn't work.
http://jsfiddle.net/kahanu/rdb00n76/9/
You could add a filter function to your selector like this:
$('input[id^="iNextPaymentDate_"]').filter(function(index) {
return parseInt($(this).val().split('/')[2]) < new Date().getFullYear();
}).addClass('k-invalid');
Fiddle: http://jsfiddle.net/rdb00n76/10/
The above code selects all inputs whose ids start with iNextPaymentDate_, then applies a filter that evaluates the current element against the current full year. To do this I split the date string on / and take the 3rd item which should be the year. Then I cast the value to int and compare the the current year.
Your actual filter function should probably be a lot more solid than the one above. For example, you could include moment.js for comparisons.
I think the forEach loop inside ListDateValidation is being executed too soon. If my understanding from your jsfiddle is correct, you're running it as soon as you instantiate the FinancialViewModel, but even though the call comes after everything else, Knockout may not have updated the DOM by this point.
There are several ways you could check this and if correct, guard against this.
But for now, to check if this is the case, I would suggest placing some logic immediately prior to the self.ListDateValidation() method call: in this logic you should just have a quick and dirty way of determining if any of those elements are present - can you temporarily (just for debugging) give these elements id attributes (just increment an int) and then run something like
if (document.getElementById("test-id-1") !== null) {
console.log("element found");
}
This will tell you if you're running the date validation too soon.
If you need a method of determining when the elements have been added then search for "javascript poll dom element added". If you can't be bothered, here's a crude method:
var elmnt,
elmntId = "YOUR ELEMENT'S ID HERE",
tmr = window.setInterval(function() {
elmnt = document.getElementById(elmntId);
if (elmnt) {
window.clearInterval(tmr); // stop the search
// do something
}
}, 15);
This method polls the DOM every 15ms, then stops when it finds that the element with the specified ID is present. 15ms corresponds to the minimum tie increment in which a browser will run - if this has since been lowered then great, but no-one would notice the difference in this context.

Obtaining elements as jQuery-objects fails when bracketing

I'm retrieving elements from a TABLE using the following syntax.
$("#table").children().children().children().html();
That gives me the contents of the first TD. Then I moved to the second one and discovered that picking it using the bracket-syntax below gives me an error message saying that html() is not a method of that object.
$("#table").children().children().children()[1].html();
Instead, I have to use innerHTML peoperty instead, like so.
$("#table").children().children().children()[1].innerHTML;
My impression is that I'm doing something wrong. While getting the result I want, I can't help feeling that there are more recommended ways to resolve this kind of call. Suggestions are welcome.
That's because html is a jQuery function, but the [1] gives you the DOM element.
You can use .eq(n) to get the nth element:
$("#table").children().children().children().eq(1).html();
...but if you're looping through them, it's very inefficient to repeat the above. Instead, consider each:
$("#table").children().children().children().each(function() {
// Use $(this).html(); for each cell's contents
});
Update In a comment you said:
I'm targeting four different elements with indexes like 143, 237 etc.
In that case, remember the initial set of elements, then use .eq as necessary:
var cells = $("#table").children().children().children();
cells.eq(143).html(...);
cells.eq(237).html(...);
You might also consider something that's less fragile if you adjust your table structure (for instance, perhaps you add a colgroup or rowgroup and now there are different levels):
var cells = $("#table td");
It is because when you use index to access the element it returns a dom element reference not a jQuery object so the .html() method won't be there.
var first = $("#table").find('td').eq(0).html();
var second = $("#table").find('td').eq(1).html();
or
var $tds = $('#table td')
var first = $tds.eq(0).html();
var second = $tds.eq(1).html();

Categories

Resources