I can't get a Master page item override working.
In the code what should I put as destinationPage?
Currently, I keep getting an error message "Invalid object for this request"
var myDoc = app.activeDocument;
var myPages=myDoc.pages;
var myItems = myDoc.pages[0].appliedMaster.allPageItems;
for (y=0; y<myItems.length; y++){
if(myItems[y] instanceof TextBox){ //&& myItems[y] instanceof TextBox ){
myItems[y].override(myPages[0]); //This bit doesn't work. What do I put here as destinationPage?
}
}
Thanks
I'm going to make a few assumptions here about what you are trying to achieve. I'm assuming that you are looking to override all of the TextFrames on the first page of your document.
var myDoc = app.activeDocument;
var myPages = myDoc.pages;
var myMasterPage = myPages[0].appliedMaster.pages[0]; // assuming single pages
var myItems = myPages[0].allPageItems; // assuming you want to override the items on the first page
for (y=0; y<myItems.length; y++) {
var myItem = myItems[y];
if (myItem.constructor === TextFrame) { // assuming you meant TextFrame instead of TextBox
myItem.override(myMasterPage);
}
}
Related
I've been trying to find a way to select all visible artboards, so i can later Quick Export them all as PNGs. I'd also love if i've could also include the exporting part inside the script, but that's not the main problem now.
I have this code that finds all the visibile artboards and stores them inside visibleArtboards, but I can't seem to find a way to make a selection of them.
var artboards = activeDoc.layers;
var visibleArtboards = [];
for (var i=0; i<artboards.length; i++){
if(artboards[i].visible){
visibleArtboards.push(artboards[i]);
}
}
activedoc.activeLayer can make a selection, but only of 1 single artboard.
If anybody can help me with the missing piece, I'd appreciate it a lot
You can get the layer ID of the artboards and add that to a selection. Using your code, visibleArtboards now is the ID of the artboard layers.
// call the source document
var activeDoc = app.activeDocument;
var artboards = activeDoc.layers;
var visibleArtboards = [];
for (var i=0; i<artboards.length; i++)
{
if(artboards[i].visible)
{
// select ID as we go along
var layerID = artboards[i].id;
visibleArtboards.push(layerID);
}
}
// Loop over the layers again and select all the art boards
for (var i=0; i<visibleArtboards.length; i++)
{
// add to current selection of layers
select_by_ID(visibleArtboards[i], true);
}
function select_by_ID(id, add)
{
if (add == undefined) add = false;
var desc1 = new ActionDescriptor();
var ref1 = new ActionReference();
ref1.putIdentifier(charIDToTypeID('Lyr '), id);
desc1.putReference(charIDToTypeID('null'), ref1);
if (add) desc1.putEnumerated(stringIDToTypeID("selectionModifier"), stringIDToTypeID("selectionModifierType"), stringIDToTypeID("addToSelection"));
executeAction(charIDToTypeID('slct'), desc1, DialogModes.NO);
} // end of selectByID()
It will, however, add the background (if included). I'm sure you can get around that.
I am using a Google Apps Script that pulls the content from a feed in a sheet.
This is the code that I'm using:
function processXML(FeedURL,sheetsFileDestinationURL,rawPasteSheetName,OPT_childNamesArray,OPT_Namespace){
var OPT_childNamesArray = ["link"]; // get only item url from the feed
var GoogleSheetsFile = SpreadsheetApp.openByUrl(sheetsFileDestinationURL);
var GoogleSheetsPastePage = GoogleSheetsFile.getSheetByName(rawPasteSheetName);
if (OPT_childNamesArray){
GoogleSheetsPastePage.getDataRange().offset(1,0).clearContent(); // get all filled cells, omitting the header row, and clear content
}
else {
GoogleSheetsPastePage.getDataRange().offset(0,0).clearContent(); // get all filled cells, INCLUDING the header row, and clear content
}
// Generate 2d/md array / rows export based on requested columns and feed
var exportRows = []; // hold all the rows that are generated to be pasted into the sheet
var XMLFeedURL = FeedURL;
var feedContent = UrlFetchApp.fetch(XMLFeedURL).getContentText(); // get the full feed content
var feedItems = XmlService.parse(feedContent).getRootElement().getChild('channel').getChildren('item'); // get all items in the feed
for (var x=0; x<feedItems.length; x++){
// Iterate through items in the XML/RSS feed
var currentFeedItem = feedItems[x];
var singleItemArray = []; // use to hold all the values for this single item/row
// Parse for specific children (requires names and namespace)
if (OPT_childNamesArray){
for (var y=0; y<OPT_childNamesArray.length; y++){
// Iterate through requested children by name and fill rows
var currentChildName = OPT_childNamesArray[y];
if (OPT_Namespace){
if (currentFeedItem.getChild(OPT_childNamesArray[y],OPT_Namespace)){
singleItemArray.push(currentFeedItem.getChildText(OPT_childNamesArray[y],OPT_Namespace));
}
else {
singleItemArray.push("null");
}
}
else {
if (currentFeedItem.getChild(OPT_childNamesArray[y])){
singleItemArray.push(currentFeedItem.getChildText(OPT_childNamesArray[y]));
}
else {
singleItemArray.push("null");
}
}
}
exportRows.push(singleItemArray);
}
// Parse for ALL children, does not require knowing names or namespace
else if (!OPT_childNamesArray){
var allChildren = currentFeedItem.getChildren();
if (x == 0){
// if looking at first item, create a header row first with column headings
var headerRow = [];
for (var h=0; h<allChildren.length; h++){
headerRow.push(allChildren[h].getName());
}
exportRows.push(headerRow);
}
for (var c=0; c<allChildren.length; c++){
singleItemArray.push(allChildren[c].getText());
}
exportRows.push(singleItemArray);
}
}
// Paste the generated md array export into the spreadsheet
if (OPT_childNamesArray){
GoogleSheetsPastePage.getRange(2,1,exportRows.length,exportRows[1].length).setValues(exportRows);
}
else if (!OPT_childNamesArray){
var maxRangeLength = 0;
var currentRowIndex = 1;
for (var x = 0; x<exportRows.length; x++){
if (exportRows[x].length > maxRangeLength){
maxRangeLength = exportRows[x].length;
}
GoogleSheetsPastePage.getRange(currentRowIndex,1,1,exportRows[x].length).setValues([exportRows[x]]);
currentRowIndex++;
}
}
}
My problem is this:
When I run this code I get:
https://url/115-396/
https://url/115-396/
https://url/115-396/
I need to remove "115-396/".
So I tryed to add this code but didn't work:
...
// Paste the generated md array export into the spreadsheet
if (OPT_childNamesArray){
for (var k = 0; k < exportRows.length; k++) {
var re = '115-396/'
var replacingItem = '';
var URL = exportRows[0].toString().replace(re, replacingItem);
}
GoogleSheetsPastePage.getRange(2,1,exportRows.length,exportRows[1].length).setValue(URL);
}
else if (!OPT_childNamesArray){
...
Edit after #Yuri reply:
// Paste the generated md array export into the spreadsheet
if (OPT_childNamesArray){
for ( k=0; k < exportRows[0].length; k++) {
var re = '115-396/'
var replacingItem = '';
exportRows[0][k] = exportRows[0][k].toString().replace(re, replacingItem);
}
GoogleSheetsPastePage.getRange(2,1,exportRows.length,exportRows[1].length).setValues(exportRows);
}
result:
https://url/
https://url/115-396/
https://url/115-396/
Basically, the regex is applied only to the first url.
How I can make that the regex is applied to all the url's?
Any help?
Thanks
You are using a for to iterate thru the exportRow array, but later on, you're not using the k iterator inside the for.
Then, you are not accessing the exportRows array, only the first position:
var URL = exportRows[0].toString().replace(re, replacingItem);
Shouldn't be?
var URL = exportRows[k].toString().replace(re, replacingItem);
In that case, it won't work, because URL it's not an array, so by doing this you are only saving the last assignation produced on the for iterator on the URL, I believe you are trying to do the following:
for ( k=0; k < exportRows.length; k++) {
var re = '115-396/'
var replacingItem = '';
exportRows[k] = exportRows[k].toString().replace(re, replacingItem);
}
And you'll have exportRows as an array of the desired url's without the 115-396 extensions.
Now you can place this on the spreadsheet with setValue as you were doing, but setValue is for strings, integers, etc, and not for arrays. For arrays you have setValues()
GoogleSheetsPastePage.getRange(2,1,exportRows.length,exportRows[1].length).setValues(exportRows);
But, then, the range of exportRows should match the range of your getRange selection, which I'm not sure it's happening.
Just to clarify it, exportRows.length is the length of the array, and exportRows[1] is the length of the string/url stored on the position 1 of the array.
Hope this helps, the question is not really clear neither the intentions, provide more info if still not working.
How to know the size of the range you're getting?
var myrange = GoogleSheetsPastePage.getRange(2,1,exportRows.length,exportRows[1].length)
Logger.log(myrange.getNumRows());
Logger.log(myrange.getNumColumns());
You'll be able to know the range you have on getRange and make it match with the exportRows size.
Make sure to check the attached documentation, and in case you have more doubts please open a new question related to it.
I'm working on a small website which i want to be able to change their dropdown menus depending on the content that i insert into a google docs file.
The code to read such content is already working fine, but now i can't set the innerHTML of my dropdown menu equal to the content of the array... Every time I try to open the dropdown it simply shows the elements with the title "undefined".
If i print the array however, it shows the correct content.
This is written via script.google for a small company I'm doing a internship for, it is written using mainly javascript, googlescript and html.
//IN CODE.gs File
function SheetNames(i) {
var app = SpreadsheetApp;
var sheet = app.getActiveSpreadsheet().getSheetByName("Options");
var name = sheet.getRange(i, 11).getValue();
return name;
}
//IN HTML File
var x = new Array();
function catcher(name){
x[i] = name;
return x;
}
window.onload = function () {
for (i = 0; i < 4; i++) {
google.script.run.withSuccessHandler(catcher).SheetNames(i+2);
var node = document.createElement("A");
var textnode = document.createTextNode(x[i]);
node.appendChild(textnode);
node.id = i;
node.value = x[i];
document.getElementById("userdrp").appendChild(node);
document.getElementById(i).innerHTML = x[i];
}
}
Expected is that the single created elements of the dropdown menu will show me the correct corresponding content in the google file.
I am now work with gs and google sheets api, but maybe here
//IN HTML File
var x = new Array();
function catcher(name){
x[i] = name;
return x;
}
variable i is not define?
I've been having a hard time with cross browser compatibility and scrapping the dom.
I've added data analytics tracking to ecommerce transactions in order to grab the product and transaction amount for each purchase.
Initially I was using document.querySelectorAll('#someId')[0].textContent to get the product name and that was working fine for every browser except internet explorer.
It took some time to figure out that it was the .textContent part that was causing ie problems.
Yesterday I changed .textContent to .innerText. From looking inside analytics it seems that the issue has been resolved for ie but now Firefox is failing.
I was hoping to find a solution without writing an if statement to check for the functionality of .textContent or .innerText.
Is there a cross browser solution .getTheText?
If not what would be the best way around this? Is there a simple solution? (I ask given my knowledge and experience with scripting, which is limited)
** added following comments **
If this is my code block:
// build products object
var prods = [];
var brand = document.querySelectorAll('.txtStayRoomLocation');
var name = document.querySelectorAll('.txtStayRoomDescription');
var price = document.querySelectorAll('.txtStayRoomSplashPriceAmount');
for(var i = 0; i < brand.length; i++) {
//set granular vars
var prd = {};
//add to prd object
prd.brand = brand[i].innerText;
prd.name = name[i].innerText;
prd.price = price[i].innerText;
prd.quantity = window.session_context_vars.BookingContext.Booking.ReservationLineItems[i].ReservationCharges.length/2;;
//add to prods array
prods.push(prd);
}
Then if I understand the syntax from the comments and the question linked to in the comment, is this what I should do:
// build products object
var prods = [];
var brand = document.querySelectorAll('.txtStayRoomLocation');
var name = document.querySelectorAll('.txtStayRoomDescription');
var price = document.querySelectorAll('.txtStayRoomSplashPriceAmount');
for(var i = 0; i < brand.length; i++) {
//set granular vars
var prd = {};
//add to prd object
prd.brand = brand[i].textContent || brand[i].innerText;
prd.name = name[i].textContent || name[i].innerText;
prd.price = price[i].textContent || price[i].innerText;
prd.quantity = window.session_context_vars.BookingContext.Booking.ReservationLineItems[i].ReservationCharges.length/2;;
//add to prods array
prods.push(prd);
}
So using or with a double bar || assigns the first non null value?
Re: your edit, not quite. The way to access methods or properties on an object (eg a DOM element) is to use dot notation if you have the name itself, or square brackets in case of variables/expressions (also works with strings, as in obj["propName"], which is equivalent to obj.propName). You can also just test the property against one element and use that from there on:
// build products object
var prods = [];
var brand = document.querySelectorAll('.txtStayRoomLocation');
var name = document.querySelectorAll('.txtStayRoomDescription');
var price = document.querySelectorAll('.txtStayRoomSplashPriceAmount');
for(var i = 0; i < brand.length; i++) {
//set granular vars
var prd = {};
//add to prd object
var txtProp = ("innerText" in brand[i]) ? "innerText" : "textContent"; //added string quotes as per comments
prd.brand = brand[i][txtProp];
prd.name = name[i][txtProp];
prd.price = price[i][txtProp];
prd.quantity = window.session_context_vars.BookingContext.Booking.ReservationLineItems[i].ReservationCharges.length/2;;
//add to prods array
prods.push(prd);
}
Regarding the line:
var txtProp = (innerText in brand[i]) ? innerText : textContent;
The in keyword checks an object to access the property (syntax: var property in object). As for the question notation (I made an error earlier, using ||, the correct thing to use was a :),
var myVar = (prop in object) ? object[prop] : false;
As an expression, it basically evaluates the stuff before the ?, and if it's true, returns the expression before the :, else the one after. So the above is the same as / a shorthand for:
if(prop in object){
var myVar = object[prop];
}
else{
var myVar = false;
}
Since you are checking between two properties only and wanting to assign one or the other, the shortest way would indeed be:
var txtProp = brand[i].innerText || brand[i].textContent;
It would basically test the first property, and if it were false or undefined, it would use the second one. The only reason I (pedantically) avoid using this is because the first test of a || b would fail even if a existed but just had a value of 0, or an empty string (""), or was set to null.
I've been trying this for a while now and could not find anything online...
I have a project, where tablerows get added to a table. Works fine.
Now I want to save the Table in the localStorage, so I can load it again. (overwrite the existing table).
function saveProject(){
//TODO: Implement Save functionality
var projects = [];
projects.push($('#tubes table')[0].innerHTML);
localStorage.setItem('projects', projects);
//console.log(localStorage.getItem('projects'));
The problem is the Array "projects" has (after one save) 2000+ elements. But all I want is the whole table to be saved to the first (or appending later) index.
In the end I want the different Saves to be listed on a Option element:
function loadSaveStates(){
alert('loading saved states...');
var projects = localStorage.getItem('projects');
select = document.getElementById('selectSave'); //my Dropdown
var length = projects.length,
element = null;
console.log(length);
for (var i = 0; i < length; i++) {
element = projects[i];
var opt = document.createElement('option');
opt.value = i;
opt.innerHTML = 'project ' + i;
select.appendChild(opt);
}
}
Can anyone tell me what I am doing wrong?
You can easily do this by jquery, are you interested in this, if yes.. then try following code
For setting the value
$.jStorage.set("projects", $.trim(projects));
For Getting the data
$.jStorage.get("projects");
For deleting the data with key
$.jStorage.deleteKey("projects");
I coose to stay with localStorage, but insted of using an Array I just let the user give every project a name and create a new Item for every Save:
function saveProject(){
//TODO: Implement Save functionality
var pname=prompt("Please enter your project name:","projectname")
var text = $('#mainTable')[0].innerHTML;
//console.log(text);
localStorage.setItem(pname, text);
//console.log(localStorage.key(2));
loadSaveStates();
}
function loadProject(){
var selected = $('#selectSave')[0].selectedIndex
//console.log(selected);
if (localStorage.key(selected) == 'jStorage'){
selected++;
}
var innerHTMLTable = localStorage[localStorage.key(selected)];
//console.log(innerHTMLTable);
$('#mainTable')[0].innerHTML = innerHTMLTable;
updateHandlers();
}
function deleteProject(){
var selected = $('#selectSave')[0].selectedIndex
var pname = $('#selectSave')[0].options[selected].value
$('#selectSave')[0].remove(selected);
localStorage.removeItem(pname);
//console.log(pname);
loadSaveStates();
}