Select a random node on every reload - neoscms

I want to select a random node on every reload. My fusion file looks like this:
randomInt = ${Math.randomInt(0, q(node).children(Neos.Neos:Document).count()}
randomNode = ${q(node).children(Neos.Neos:Document).get(this.randomInt)}
Unfortunately the result is stored in the cache. That means that only after the cache get flushed a new node will be returned. How can I prevent this? I have already experimented with the cache rules a little bit, but I didn't come up with a solution yet.

The element that I want to use is on every page. That's why something like the unchached mode would be a really bad idea.
In my situation the output is only a array of strings. So I did following in my Fusion.
Generate "almost" a Array in Fusion
allMyStrings = Neos.Fusion:Loop {
items = ${q(node).children(Neos.Neos:Document).get()}
itemName = 'node'
itemRenderer = ${"'" + q(node).property('testString') + "'"}
#glue = ','
}
Pick a random array in JS
<p id='replaceMe'></p>
<script>
var quoteArray = [{allMyStrings -> f:format.raw()}]
var randomIndex = Math.floor(Math.random() * quoteArray.length);
var randomElement = quoteArray[randomIndex];
document.getElementById('replaceMe').outerHTML= '<p>' + randomElement + '</p>';
</script>
A bit hacky but it works and it don't harm the performance of the website

Related

Properly attaching pictures to an email with google scripts

I'm trying to make a script with google forms and sheets to help with the automation and tracking our technicians pictures on the jobsite.
The setup is they take pictures of the jobsite and fill out a google form with the information and attach the pictures there. When the form gets submitted, it runs this script to send an email to a predetermined email that everyone in the office can see.
So far I am able to get the email to send the information from the form besides the pictures.
The information for the attached pictures come in as a drive url that is all dumped into one cell as a string.
"https://drive.google.com/open?id=xxxxxxxx, https://drive.google.com/open?id=yyyyyyyy, https://drive.google.com/open?id=zzzzzzzz"
I convert this string to an array using .split(" ,) which outputs this.
[https://drive.google.com/open?id=xxxxxxxx, https://drive.google.com/open?id=yyyyyyyy, https://drive.google.com/open?id=zzzzzzzz]
I then iterate through the array and use.slice(33) to get rid of the url so all that I'm left with is the drive id (there is probably a better way of doing this but it works for now).
[xxxxxxxx, yyyyyyyy, zzzzzzzz]
This is the part where I'm having trouble.
I then iterate agian through that array and grab the driveID and the get the file as a JPEG.
I then use .push to put it into another array that I'm using to attachment them to the email.
The issue is that I think I'm not doing this step properly by not pushing the correct thing into the array and/or assuming that MailApp.sendEmail can even take an array for attachments.
I'm also not entirely sure how [Blobs] work and how to use them properly and that's probably where I'm getting stuck.
Again, this is code is made with very little experience and could probably be optimized futher but at the moment, I just need to have it attach the pictures properly to show that it works.
function onFormSubmit(e) {
//for testing purposes
var values = e.namedValues;
//gets the form's values
var pureValues = e.values;
//sets the values
var email = pureValues[1];
var woNum = pureValues[2];
var firstN = pureValues[3];
var lastN = pureValues[4];
var desc = pureValues[5];
var superDuperRawPics = pureValues[6];
//splits the picture urls into an array
var superRawPics = superDuperRawPics.split(", ");
//slices the url part off to get the drive ID
var i, rawPics =[]
for (i = 0; i < superRawPics.length; ++i) {
rawPics.push(superRawPics[i].slice(33))
}
//takes the array of ID's and gets the drive file
var j, picAttach =[]
for (j = 0; j < rawPics.length; ++j) {
var driveID = DriveApp.getFileById(rawPics[j]);
var drivePic = driveID.getAs(MimeType.JPEG);
picAttach.push(drivePic);
}
//sets the subject of the email to be Jobsite Pictures and the work number
var subject = "Jobsite Pictures" + " " + woNum;
//sets the body of the email
var body = "Technician: " + email + " \n" +
"WO#: " + woNum + " \n" +
"Customer: " + firstN + " " + lastN + " \n" +
"Description: " + desc;
//for checking if the vars are set correctly
Logger.log(superDuperRawPics);
Logger.log(superRawPics);
Logger.log(rawPics);
Logger.log(picAttach);
Logger.log(subject);
Logger.log(body);
//sends email to me with the new info
MailApp.sendEmail('example#domian.com', subject, body, {attachments: [picAttach]});
}
If you just want to attach them then use options attachments
I was being dumb and added brackets to the attachments: when it didn't need them.
The correct way is this.
MailApp.sendEmail('example#domian.com', subject, body, {attachments: picAttach});
Changing this has the script sending emails with the pictures attached.

want to store promise value in an array

I want to get all the values from a registration page and store all values in an array. How can I do that in protractor?
var arr = new Array(); //declare array
InputName.getAttribute("value")
.then(function(value){
arr[0]=value; // want to store promise value in an array
});
console.log(arr[0]);
If you run your code, it will first log arr[0] and then resolve Promise. Therefore, you may access that array's values in the next Promise. Something like this
var arr = new Array(); // <- this is by the way bad practice, use 'let arr = [];'
InputName.getAttribute("value")
.then(function(value) {
arr[0]=value; // I would use arr.push(value)
});
anotherInput.getAttribute("value")
.then(function(value) {
console.log(arr[0]); // your value should be accessible here
arr.push(value) // push another value
});
But, honestly, I've been working with Protractor fo a while now and I still have difficulties understanding promises... This why I'm using async/await in my tests so if I were to implement something like that I would end up having the following
let arr = [];
let value1 = await InputName.getAttribute("value");
arr.push(value1);
console.log(arr[0]);
Clear, neat code with no hustle. Plus protractor team is actually removing promise_manager, so one day when you update it your code will not work anymore. Then why not switch earlier

Unable to set a javascript date object to a cell hidden by filter

I have a script which checks certain conditions to send reminders emails or sms to my clients. the only issues I'm finding is that if I try to write a cell that is hidden by a filter, the script executes but the data is not changed in any way.
I'll write a short version of the whole script:
function test(){
var nowTime = new Date();
var sheet = SpreadsheetApp.getActiveSpreadsheet();
var lastrow =sheet.getLastRow();
var lastcol =sheet.getLastColumn();
var fullData =cell.offset(0, 0,lastrow-
cell.getRow()+1,lastcol).getValues();
var cell = sheet.getRange("A2");
var i=0;
while (i<fullData.length){
var reminderType =0;
var row = fullData[i];
if (row[0] == 1) {sendreminder();cell.offset(i, 2).setValue(new Date());}
}
}
if for example the first column has hidden all the rows with 1 the script executes and sends all the reminders but ignore the setvalue(), if the rows are visible it works perfectly.
One solution can de to remove the filter but would be very annoying since we use the filter a lot and the script is triggered by time every 10 minutes so I would be working on the sheet and suddenly the filter get removed to run the script.
I have tried with cell.offset, getrange etc.. without any success ... Ideas?
EDIT: The problem seems to be only if I try to write a date if (row[0] == 1) {cell.offset(i, 1).setValue(new Date());}
For instance I'm writing another information (a number) in a different column and that cell gets updated.
The rest remain the same
here is a test sheet I created:
https://docs.google.com/spreadsheets/d/1-FNDGmvCc8nRFTG65Sj9L2RhGn8R3DtwR3llwBG5-FA/edit#gid=0
For now I added this code to save the state of the filter and reestablish it at the end. It's not really elegant and still add a lot of chances of something being messed up or the script failing but it's the less invasive solution I came out with. Does someone has a better one?
// at the beginning
if (sheet1.getFilter()){
var filterRange= sheet1.getFilter().getRange();
var filterSetting = [];
var i=0;
while (i<filterRange.getNumColumns()-1) {filterSetting[i]= sheet1.getFilter().getColumnFilterCriteria(i+1);sheet1.getFilter().removeColumnFilterCriteria(i+1);i++; }
}
// At the end
if (sheet1.getFilter()){
var i=0;
while (i<filterRange.getNumColumns()-1) {if (filterSetting[i]) sheet1.getFilter().setColumnFilterCriteria(i+1, filterSetting[i]);i++; }
}
Given the fact the problem is not writing in the hidden row as it was pointed out, the solution is to use the formatdate to format the value before writing it in the cell.
Not ideal either since regional formattings might prevent the script from working on different accounts but sure better solution than disabling the filters.
here is the code i needed to add:
var nowTime = new Date();
var timeZone = Session.getScriptTimeZone();
var nowTimeFormatted = Utilities.formatDate(nowTime, timeZone, 'MM/dd/yyyy HH:mm:ss');
any idea on how to improve this script or to solve the original problem without workarounds is appreciated :)

concatenating jQuery objects

Below is the prototype of what I am trying to do.
var entry_set = $;
// start to loop data
for([])
{
// create HTML element to represent that data
$('<div></div>')
.data([])
.addClass([])
.on([])
.insertAfter(entry_set);
}
// modify DOM only once all the entries are consolidated to a single jQuery object
entry_set.appendTo('.entries');
The comments say it all. In short - the idea is to modify document DOM only once when inserting data. I would usually go HTML string approach (simply concatenating the same structure using a string), but I am interested whether anything similar to this might work as well.
You could create an empty DOM element and .append() to that
var entry_set = $("<div>"); //empty dom element
// start to loop data
var i = 4;
while(i--) {
// create HTML element to represent that data
var item = $('<div>', {
text: "test " + i
});
entry_set.append(item);
}
// modify DOM only once all the entries are consolidated to a single jQuery object
$("body").append(entry_set.children());​
working demo at: http://jsfiddle.net/F2J6g/1/
EDIT
You can also start with an empty collection and use .add()
var entry_set = $(); //empty collection
// start to loop data
var i = 4;
while(i--) {
// create HTML element to represent that data
var item = $('<div>', {
text: "test " + i
});
entry_set = entry_set.add(item);
}
// modify DOM only once all the entries are consolidated to a single jQuery object
$("body").append(entry_set);
http://jsfiddle.net/F2J6g/2/
#Guy, I don't think you will get the desired HTML output. try using "wrap".
Sample Syntax:
$('.OuterDiv').wrap('<div class="abc" />');
Unfortunately, because those objects aren't actually attached to any heirarchy, calling insertAfter doesn't actually mean anything. What you'll need to do is put them inside a containing div, maybe something like this:
var entry_set = $('<div>');
// start to loop data
for([])
{
// create HTML element to represent that data
$('<div></div>')
.data([])
.addClass([])
.on([])
.appendTo(entry_set);
}
// modify DOM only once all the entries are consolidated to a single jQuery object
entry_set.appendTo('.entries');
I haven't tested that, but I think it should work.

How to avoid to crash a browser?

I need a way to get the friend ids of a user.
I written this code but my browser crashes ( maybe because I have 2500 friends ):
var query = FB.Data.query('SELECT uid2 FROM friend WHERE uid1 = me()');
query.wait(function(rows) {
var i;
for(i=0;i<rows.length;i++){
document.getElementById('friends').innerHTML += i + ') ' + rows[i].uid2 + '<br />';
}});
Is there a less CPU consuming approach ?
At VERY least, compile all your HTML in a variable and then pass it to DOM in one .innerHTML assignment. Right now your forcing page redraw two times per each of your 2500 friends because browser needs to update its own internal understanding of page on innerHTML read in += and then once again on writing back.
query.wait(function(rows) {
var i;
var html = "";
for(i=0;i<rows.length;i++){
html += i + ') ' + rows[i].uid2 + '<br />';
}
document.getElementById('friends').innerHTML = html
}
You can also use some other approaches, like storing generated strings in an array and then joining them together and assigning to HTML, but that's just optimizing around JS immutable strings and garbage collector. Some JS engines may eventually do this much better that you'd do by hand. Doing innerHTML assignment once, however, is almost guaranteed to be huge speed increase, because it literally means "regenerate everything and then apply a little bit and encode everything back again" and there's hardly any way to automatically optimize doing this inside loop inside JS+HTML engines junction.