I have a function for adding the contents of a separate google document at the cursor point within the active document, but I haven't been able to get it to work. I keep getting the "Element does not contain the specified child element" exception, and then the contents gets pasted to the bottom of the document rather than at the cursor point!
function AddTable() {
//here you need to get document id from url (Example, 1oWyVMa-8fzQ4leCrn2kIk70GT5O9pqsXsT88ZjYE_z8)
var FileTemplateFileId = "1MFG06knf__tcwHWdybaBk124Ia_Mb0gBE0Gk8e0URAM"; //Browser.inputBox("ID der Serienbriefvorlage (aus Dokumentenlink kopieren):");
var doc = DocumentApp.openById(FileTemplateFileId);
var DocName = doc.getName();
//Create copy of the template document and open it
var docCopy = DocumentApp.getActiveDocument();
var totalParagraphs = doc.getBody().getParagraphs(); // get the total number of paragraphs elements
Logger.log(totalParagraphs);
var cursor = docCopy.getCursor();
var totalElements = doc.getNumChildren();
var elements = [];
for (var j = 0; j < totalElements; ++j) {
var body = docCopy.getBody();
var element = doc.getChild(j).copy();
var type = element.getType();
if (type == DocumentApp.ElementType.PARAGRAPH) {
body.appendParagraph(element);
} else if (type == DocumentApp.ElementType.TABLE) {
body.appendTable(element);
} else if (type == DocumentApp.ElementType.LIST_ITEM) {
body.appendListItem(element);
}
// ...add other conditions (headers, footers...
}
Logger.log(element.editAsText().getText());
elements.push(element); // store paragraphs in an array
Logger.log(element.editAsText().getText());
for (var el = 0; el < elements.length; el++) {
var paragraph = elements[el].copy();
var doc = DocumentApp.getActiveDocument();
var bodys = doc.getBody();
var cursor = doc.getCursor();
var element = cursor.getElement();
var container = element.getParent();
try {
var childIndex = body.getChildIndex(container);
bodys.insertParagraph(childIndex, paragraph);
} catch (e) {
DocumentApp.getUi().alert("There was a problem: " + e.message);
}
}
}
You want to copy the objects (paragraphs, tables and lists) from the document of 1MFG06knf__tcwHWdybaBk124Ia_Mb0gBE0Gk8e0URAM to the active Document.
You want to copy the objects to the cursor position on the active Document.
You want to achieve this using Google Apps Script.
If my understanding is correct, how about this answer? Please think of this as just one of several possible answers.
Modification points:
In your script, appendParagraph, appendTable and appendListItem are used at the 1st for loop. I think that the reason that the copied objects are put to the last of the document is due to this.
var body = docCopy.getBody(); can be put to the out of the for loop.
In your case, I think that when the 1st for loop is modified, 2nd for loop is not required.
When above points are reflected to your script, it becomes as follows.
Modified script:
function AddTable() {
var FileTemplateFileId = "1MFG06knf__tcwHWdybaBk124Ia_Mb0gBE0Gk8e0URAM";
var doc = DocumentApp.openById(FileTemplateFileId);
var docCopy = DocumentApp.getActiveDocument();
var body = docCopy.getBody();
var cursor = docCopy.getCursor();
var cursorPos = docCopy.getBody().getChildIndex(cursor.getElement());
var totalElements = doc.getNumChildren();
for (var j = 0; j < totalElements; ++j) {
var element = doc.getChild(j).copy();
var type = element.getType();
if (type == DocumentApp.ElementType.PARAGRAPH) {
body.insertParagraph(cursorPos + j, element);
} else if (type == DocumentApp.ElementType.TABLE) {
body.insertTable(cursorPos + j, element);
} else if (type == DocumentApp.ElementType.LIST_ITEM) {
body.insertListItem(cursorPos + j, element);
}
}
}
It seems that DocName is not used in your script.
References:
insertParagraph()
insertTable()
insertListItem()
If I misunderstood your question and this was not the result you want, I apologize. At that time, can you provide the sample source Document? By this, I would like to confirm it.
Related
I am writing a script for an active doc in Illustrator. The active doc already has the spot swatch for "LEAD" in it. All the paths I have to set and symbols need to be set to this swatch. I have worked my way around it by deleting the swatch then re-adding it to the doc. This works for all my paths and objects created. There are 3 symbols in the active doc that are being placed by scrip, that are already set to the spot swatch. When my script deletes the swatch it resets the symbol to 100% black process. Is there a way to pull the swatch from the active doc?All path items reqiure the leadSpotColor variable to set that color. The LEAD swatch already exist in the active doc. If i do not add the swatch remove line before hand it errors out, but the swatch remove line sets my symbols already in the active doc to 100% process black, and they also need to be set to the LEAD swatch.
if ( app.documents.length = "LEAD" ) {
swatchToDelete = app.activeDocument.swatches["LEAD"];
swatchToDelete.remove();
}
var leadSpot = doc.spots.add();
var leadSpotColor = new CMYKColor();
leadSpotColor.cyan = 0;
leadSpotColor.magenta = 0;
leadSpotColor.yellow = 0;
leadSpotColor.black = 100;
leadSpot.name = "LEAD";
leadSpot.colorType = ColorModel.SPOT;
leadSpot.color = leadSpotColor;
var leadSpotColor = new SpotColor();
leadSpotColor.spot = leadSpot;
Why would you want to delete the swatch if you can just edit it ?
var main = function(){
var doc,
leadClr, c;
if(!app.documents.length) return;
doc = app.activeDocument;
leadClr = getLeadColor(doc);
if ( leadClr===null ) {
var leadSpot = doc.spots.add();
var leadSpotColor = new CMYKColor();
leadSpotColor.cyan = 0;
leadSpotColor.magenta = 0;
leadSpotColor.yellow = 0;
leadSpotColor.black = 100;
leadSpot.name = "LEAD";
leadSpot.colorType = ColorModel.SPOT;
leadSpot.color = leadSpotColor;
var leadSpotColor = new SpotColor();
leadSpotColor.spot = leadSpot;
}
else {
c = leadClr.color.spot.color;
c.cyan = 0;
c.magenta = 0;
c.yellow = 0;
c.black = 100;
}
};
var getLeadColor = function(doc){
var clrs = doc.swatches,
n = clrs.length;
while (n-- ) {
if ( clrs[n].name=="LEAD" ) return clrs[n];
}
return null;
}
main();
I would recommend adding some prevention mechanism like ensure swatch is actually a spot prior to reach teh spot property.
First of all first line of your code is wrong
if ( app.documents.length = "LEAD" )
How you can compare length with string "LEAD", its should be a number and also in if statement we use conditional operator and what you are doing is assigning value in if statement.
Here is the script for LEAD spot, that will give you spot color if exist otherwise it will create new spot color with name "LEAD"
function main() {
var currentDocument;
var leadSpotColor;
if (!app.documents.length) {
alert("No document is open");
return;
}
currentDocument = app.activeDocument;
leadSpotColor = getLeadSpotColor(currentDocument);
applyColorToAllPath(leadSpotColor, currentDocument);
}
function getLeadSpotColor(currentDocument) {
try {
var leadSpotColor = currentDocument.spots.getByName('LEAD')
return leadSpotColor;
} catch (e) {
var color = new CMYKColor();
color.cyan = 0;
color.magenta = 0;
color.yellow = 0;
color.black = 100;
var newSpot = currentDocument.spots.add();
newSpot.name = "LEAD";
newSpot.colorType = ColorModel.SPOT;
newSpot.color = color;
var leadSpotColor = new SpotColor();
leadSpotColor.spot = newSpot;
return leadSpotColor;
}
}
function applyColorToAllPath(leadSpotColor, currentDocument) {
// Change code as per your requiremnt. I just handled for pathItems. You can similary for symbols.
var pathItems = currentDocument.pathItems;
for (var i = 0; i < pathItems.length; i++) {
pathItems[i].filled = true;
pathItems[i].fillColor = leadSpotColor;
pathItems[i].stroke = true;
pathItems[i].strokeColor = leadSpotColor;
}
}
main();
I'm trying to make a slideshow of pictures and send them to an another window. But after selecting images and pressing the button for showing slideshows, nothing happens. I'm using firebug to detect bugs and when I'm going wrong. But I'm not getting any error from firebug so I gotta ask you guys. This is my code.
var infoBox;
var formTag;
var imgUrlList;
var imgTextList;
var windVar;
var urlList;
var textList;
function init() {
var i;
infoBox = document.getElementsByClassName("outerBox");
for (i=0; i<infoBox.length; i++) {
infoBox[i].onmouseover = showInfoBox;
infoBox[i].onmouseout = hideInfoBox;
}
formTag = document.getElementsByTagName("input");
for (i=0; i<formTag.length; i++) {
formTag[i].onclick = checkedBox;
}
windVar = null;
imgTextList = [];
imgUrlList = [];
}
window.onload = init;
function showInfoBox() {
var showInfo;
showInfo = this.getElementsByClassName("innerBox")[0];
showInfo.style.visibility = "visible";
}
function hideInfoBox() {
var hideInfo;
hideInfo = this.getElementsByClassName("innerBox")[0];
hideInfo.style.visibility = "hidden";
}
function checkedBox() {
var ImgNode, ImgTag;
for (i=0; i<formTag.length; i++) {
imgNode = this.parentNode.parentNode.firstChild;
imgTag = imgNode.nextSibling
if (this.checked) {
imgTag.className = "markedImg";
}
else {
imgTag.className = "unmarkedImg";
}
}
}
function slideShowBtn() {
var url, i, filename;
imgUrlList.length = 0;
imgTextList.length = 0;
for (i=0; i<formTag.length; i++) {
if (formTag.checked) {
url = infoBox.firstChild.getElementsByTagName("img")[i].src;
filename = infoBox.firstChild.getElementsByTagName("span")[i].src;
imgUrlList.push(url);
imgTextList.push(filename);
}
else break;
}
newWindow(700,600,"slideshow.htm");
}
function newWindow(width,height,fileName) {
var windProporties;
windProporties = "top=100, left=100,toolbar=no,status=no,menubar=no,scrollbars=no,resizable=no,width=" + width + ",height=" + height;
if (windVar != null) if (windVar.closed == false) windVar.close();
windVar = window.open(fileName,"bildspel",windProporties);
}
The formTag variabel is from a checkbox-input-tag. And it's from that I decide which pictures are selected and will be moved to the new page. ImgTextList and imgUrlList are global variables that'll also be in the next window. infoBox is a reference to a div class which is called OuterBox and inside it is an another div-class named innerBox, it's in the innerBox classdiv which the img and span-tags are. The code for the slideshow is already written and I'm just writing code for sending the variables to it.
Edit: I should have been a little more informative. But here's the code for the slideshow part where window.opener is present. And I've added all the remaining code that's above. How do you embed files?
// JavaScript for the slideshow page
// ----- Global variables -----
var imgUrlList = window.opener.imgUrlList; // Array with filenames of selected images. Initialized to an empty array.
var imgTextList = window.opener.imgTextList; // Array with image texts of selected images. Initialized to an empty array.
var slideshowMenu = null; // Reference to the image menu.
var slideshowImg = null; // Reference to the slideshow img tag.
var slideshowText = null; // Reference to the tag for the image text.
// ---- Create the image menu and show the first image. Also attach event handlers. ----
function initSlideshow() {
// Create a image list from the content of the variable imgUrlList
var HTMLcode = "<select id='imgMenu'>";
for (var i=0; i<imgTextList.length; i++) {
HTMLcode += "<option>" + imgTextList[i] + "</option>";
} // End for
HTMLcode += "</select>";
document.getElementById("iMenu").innerHTML = HTMLcode; // Add the select and option tags to the HTML code
slideshowMenu = document.getElementById("imgMenu"); // Save a reference to the menu's select tag
slideshowMenu.selectedIndex = 0; // Select the first option in the menu
slideshowImg = document.getElementById("slideshowBox").getElementsByTagName("img")[0];
slideshowText = document.getElementById("slideshowBox").getElementsByTagName("div")[0];
// Show the first image
slideshowImg.src = imgUrlList[0];
slideshowText.innerHTML = imgTextList[0];
// Attach event handlers
var slideshowButtons = document.getElementById("slideshowForm").getElementsByTagName("input");
slideshowButtons[0].onclick = showPrevImage;
slideshowButtons[1].onclick = showNextImage;
slideshowMenu.onchange = showSelectedImage;
} // End initSlideshow
window.onload = initSlideshow;
// ---- Show previous image in the list (menu) ----
function showPrevImage() {
var ix = slideshowMenu.selectedIndex; // Index for the current image
if (ix > 0) { // If it's not already the first image
slideshowMenu.selectedIndex = ix-1;
slideshowImg.src = imgUrlList[ix-1];
slideshowText.innerHTML = imgTextList[ix-1];
}
} // End showPrevImage
// ---- Show next image in the list (menu) ----
function showNextImage() {
var ix = slideshowMenu.selectedIndex; // Index for the current image
if (ix < slideshowMenu.length-1) { // If it's not already the last image
slideshowMenu.selectedIndex = ix+1;
slideshowImg.src = imgUrlList[ix+1];
slideshowText.innerHTML = imgTextList[ix+1];
}
} // End showNextImage
// ---- Show selected image in the list (menu) ----
function showSelectedImage() {
var ix = slideshowMenu.selectedIndex; // Index for the selected image
slideshowImg.src = imgUrlList[ix];
slideshowText.innerHTML = imgTextList[ix];
} // End showSelectedImage
Um, you never do anything to send it. Either pass it as a querystring parameter or have the child reference a global variable in the opener.
var foo = window.opener.imgUrlList;
I have to fetch data from the PHP web service in an array and then display it on HTML page using JavaScript. I have used a for loop to do so. But it doesn’t render proper output. Due to innerHTML the output gets replaced. Please help with your suggestions. Here is my code:
function jsondata(data){
alert("JSONdata");
var parsedata = JSON.parse(JSON.stringify(data));
var main_category = parsedata["main Category"];
for (var i = 0; i <= main_category.length; i++) {
menu = JSON.parse(JSON.stringify(main_category[i]));
menu_id[i] = menu['mcatid'];
menu_title[i] = menu['mcattitle'];
menu_img[i] = menu['mcatimage'];
pop_array.push(menu_id[i], menu_title[i], menu_img[i]);
//alert(pop_array);
for (var i = 0; i < main_category.length; i++) {
alert("for start");
var category = document.createElement("li");
document.getElementById("mylist").appendChild(category);
//document.getElementById("mylist").innerHTML='<table><tr><td>'+pop_array[i]+'</td></tr></table>';
document.write(pop_array.join("<br></br>"));
alert("for end");
}
}
}
Although I don't get why pop_array was used here but I assume that you are trying to display the category info as a li tag.
You should set category.innerHTML instead of document.getElementById("mylist").innerHTML.
function jsondata(data){
var parsedata = JSON.parse(JSON.stringify(data));
var main_category = parsedata["main Category"];
for (var i = 0; i < main_category.length; i++) {
var menu = main_category[i];
var category = document.createElement("li");
category.innerHTML = menu['mcattitle']; // construct your own html here
document.getElementById("mylist").appendChild(category);
}
}
Following the documentation sample, I'm trying to create a function that searchs for a numerated list in a google document and, if finds it, adds a new item to that list. But I get this error: Cannot find method setListId(string). (line 21, file "test") or, if I change line 21 content (replacing elementContentfor newElement), I get the message: Preparing for execution... and nothing happens. How to fix it?
This is my code:
function test() {
var elementContent = "New item testing"; // a paragraph with its formating
var targetDocId = "1R2c3vo9oOOjjlDR_n5L6Tf9yb-luzt4IxpHwwZoTeLE";
var targetDoc = DocumentApp.openById(targetDocId);
var body = targetDoc.getBody();
for (var i = 0; i < targetDoc.getNumChildren(); i++) {
var child = targetDoc.getChild(i);
if (child.getType() == DocumentApp.ElementType.LIST_ITEM){
var listId = child.getListId();
var newElement = body.appendListItem(elementContent);
newElement.setListId(newElement);
Logger.log("child = " + child);
}
}
}
Following my comment, I tried to play with your script to see what happened and I came up with that code below...
I'm not saying it solves your issue and/or is the best way to achieve what you want but at least it gives a result that works as expected.
Please consider it as a "new playground" and keep experimenting on it to make it better ;-)
function test() {
var elementContent = "New item testing"; // a paragraph with its formating
var targetDocId = DocumentApp.getActiveDocument().getId();
var targetDoc = DocumentApp.openById(targetDocId);
var body = targetDoc.getBody();
var childIndex = 0;
for (var i = 0; i < targetDoc.getNumChildren(); i++) {
var child = targetDoc.getChild(i);
if (child.getType() == DocumentApp.ElementType.LIST_ITEM){
while(child.getType() == DocumentApp.ElementType.LIST_ITEM){
child = targetDoc.getChild(i)
childIndex = body.getChildIndex(child);
Logger.log(childIndex)
i++
}
child = targetDoc.getChild(i-2)
var listId = child.getListId();
Logger.log(childIndex)
var newElement = child.getParent().insertListItem(childIndex, elementContent);
newElement.setListId(child);
break;
}
}
}
after dynamicly creating some iframes, setting src and onload, I expect that the contents would be available for putting it to an array and sort the array. Next would be removing the iframes (interesting content already put in array) and create a table on my HTML-page. When no alert is set before sorting, the array is empty as the onload fires just before finishing the script. When an alert is place before sorting,I found the onload-procedure fired, array was populated and everything works fine?!! But I don't want to put an alert, can anyone explain what I did wrong? It's my first script so please help me to understand.
function LoadFile( ) {
var FName, PName, myID, myFrame;
var myBody = document.getElementById("StartList");
for ( var i = 0; i < FileList.length; i++ ) {
// Read input file into frame
FName = FileList[i].FName;
PName = FName + ".html";
myID = "iframe" + i;
// Create frame.
myFrame = document.createElement("iframe");
myFrame.setAttribute("id", myID);
myFrame.setAttribute("width","0");
myFrame.setAttribute("height","0");
myFrame.setAttribute('src', PName);
//Attach onload-event to frame, triggering ReadTableInfo.
if (myFrame.attachEvent){
myFrame.attachEvent("onload", function(){
ReadTableInfo();
});
} else {
myFrame.onload = function(){
ReadTableInfo();
};
}
myBody.appendChild(myFrame);
}
}
function ReadTableInfo() {
var a = document.getElementsByTagName("iframe")[idx];
var p = FileList[idx].FName;
var b = (a.contentWindow || a.contentDocument);
var td;
if ( b.document) {
b = b.document;
// Get and process table with functions and procedures.
var myTable = b.getElementsByTagName("Table")[5];
var myList = myTable.getElementsByTagName("TR");
var Name = "";
var Desc = "";
for ( var j = 0; j < myList.length; j++) {
Name = myTable.getElementsByTagName("TR") [j].getElementsByTagName("A")[0].innerHTML;
if ( myTable.getElementsByTagName("TR")[j].getElementsByTagName("TD")[1] != null) {
td = myTable.getElementsByTagName("TR")[j].getElementsByTagName("TD")[1];
Desc = td.textContent || td.innerText || "";
}
if ( searchval == "" || ( TestVal.test(Name) && searchkey == 1 ) || ( TestVal.test(Desc) && searchkey == 2 ) ) {
ProcList[ProcList.length++] = new AddProcList(Name.toLowerCase(), p.toLowerCase(), Desc);
}
Name = "";
Desc = "";
}
idx++;
}
}
function UpdateList( opt ) {
searchval = document.getElementById("edtSearchVal").value;
TestVal = new RegExp(".", "i");
if ( searchval !== "" ) {
if ( opt == 2 ) {
TestVal = new RegExp(searchval, "i"); // searchpattern for RegExp descriptions
} else {
TestVal = new RegExp(searchval.replace(" ","_"), "i"); // searchpattern for RegExp.
}
}
switch ( opt ) {
case 1: searchkey = 1;
break;
case 2: searchkey = 2;
break;
default:
searchkey = 3;
}
Init();
// Get package names from index.
SetFileList(); // Determines which external files to examine.
LoadFile(); // Loads the external files into iframes to be used later.
alert("Start generating list, this may take a while."); // Necessary to read frames! Don't know why???
var sortkeys = {FName:"a",PName:"a"}; // Sorting order of ProcList, which will be the listorder.
ProcList.keySort(sortkeys); // Sort ProcList.
TableCreate(); // Make new table with all entries in ProcList
}
Thanks for any comments, just here to learn from others :))
your LoadFile(); is loading content to iframe , and alert() is giving just enough time for iframe content to load completely, hence rest of the code works. If you remove alert then rest of the code is executed immediately before iframe content is loaded.
I would suggest to put onload even inside iframe page as well. Then propagate this event to parent window. To access parent container window you can do window.parent inside iframe.