Is there a way to tell the count of characters of all text fields in some of our content items? We need to estimate a translation price for our content items.
You can use Delivery API to retrieve your items and run a quick javascript to count the characters for you. First, get all your items (or a subset, depending on what you need) with the call excluding all the modular content (linked items) like this:
https://deliver.kenticocloud.com/<projectid>/items?depth=0
Then you can use browser console to run this piece of code:
var response = JSON.parse(document.getElementsByTagName("BODY")[0].textContent);
var noOfChars = 0;
for (var x = 0; x < response.items.length; x++) {
var p = response.items[x].elements;
for (var key in p) {
if (p[key].type=='rich_text' || p[key].type=='text') {
noOfChars += strip(p[key].value).length;
}
}
}
noOfChars;
function strip(html)
{
var tmp = document.createElement("DIV");
tmp.innerHTML = html;
return tmp.textContent || tmp.innerText || "";
}
And hit enter. This is what the result will look like:
Related
I am using pdfMake to generate table reports. Some of the reports are very wide and dont fit on a standard page width, even in landscape mode. Currently, pdfMake is cutting off the table content when it overflows past the page margin.
I would like to page break the table when it is too wide, much like when the rows overflow to the next page.
Is this possible using pdfMake?
Can using pageBreakBefore callback function help for this?
Thank you
Yes, this is possible with pdfMake, even though not currently a feature.
To achieve this, you can just break overflowing columns into another table. We can put all the tables in an array, then just set them in the docDefinition as follows.
Any common attributes you want in the tables can be defined in the Template constructor.
for (var i = 0; i < tables.length;i++) {
docDefinition.content[i] = new Template();
docDefinition.content[i].table.body = tables[i];
docDefinition.content[i].table.widths = widths[i];
if (i > 0) {
docDefinition.content[i].pageBreak = 'before';
}
}
function Template(){
this.table = {
dontBreakRows: true
};
//zebra stripes layout
this.layout = {
fillColor: function (row, node, col) {
return (row % 2 === 0) ? '#CCCCCC' : null;
}
}
}
How do we determine if a column will overflow? We have two options:
If you are using bootstrap datatables, you can use the "width" attribute in the html.
pdfmake calculates the actual width, but you may have to dig around in pdfmake.js.
Then, just loop through, adding widths until you exceed your limit (my limit was for 8pt font). You can do this for THs then save those column splits and use those for the TDs.
If the final page is just barely overflowing, we don't want the final page to have just one column, we want each page to have roughly the same width. We calculate the number of pages needed, then find the desired break point from there. To link the pages together more easily, you can add a row number column at the beginning of each table.
var colSplits = [];
var tables = new Array();
function parseTHs(colSplits, tables) {
var colSum = 0;
var pageSize = 1120-7*rows.toString().length;
var paddingDiff = 11.9;
var columns = 0;
var prevSum;
var i = 0;
var width = $(".dataTables_scrollHeadInner > table").width();
var pages = Math.ceil(width/pageSize);
console.log("pages: "+pages);
var desiredBreakPoint = width/pages;
console.log("spread: "+desiredBreakPoint);
var limit = pageSize;
var row = ['#'];
var percent = '%';
widths.push(percent);
$(".dataTables_scrollHeadInner > table > thead > tr:first > th").each(function() {
prevSum = colSum;
colSum += $(this).outerWidth()-paddingDiff;
//if adding column brings us farther away from the desiredBreakPoint than before, kick it to next table
if (colSum > limit || desiredBreakPoint-colSum > desiredBreakPoint-prevSum) {
tables[i] = [row];
row = ['#'];
widths.push(percent);
colSplits.push(columns);
i++;
desiredBreakPoint += width/pages;
limit = prevSum+pageSize;
}
row.push({text: $(this).text(), style:'header'});
widths.push(percent);
columns++;
});
//add the final set of columns
tables[i] = [row];
}
function parseTDs(colSplits, tables) {
var currentRow = 0;
$("#"+tableId+" > tbody > tr").each(function() {
var i = 0;
var row = [currentRow+1];
var currentColumn = 0;
var split = colSplits[i];
$(this).find("td").each(function() {
if (currentColumn === split) {
tables[i].push(row);
row = [currentRow+1];
i++;
split = colSplits[i];
}
row.push({text: $(this).text()});
currentColumn++;
});
//add the final set of columns
tables[i].push(row);
currentRow++;
});
}
parseTHs(colSplits, tables);
parseTDs(colSplits, tables);
Note: If you want the columns to fill all the available page, there's a good implementation for that at this link.
I just added '%' for the widths and added that code to pdfmake.js.
Hope this helps!
Just add dontBreakRows property in your table object like this
table: {
dontBreakRows: true,
widths: [30,75,48,48,48,48,48,115],
body: []
}
Also, you can make the page wider and change the page orientation as landscape.
pageSize: "A2",
pageOrientation: "landscape",
I have successfully linked my BigCommerce account to my Google Sheets (Drive) account so every time I receive a new order in my store the order is automatically exported into a Google Sheet. Unfortunately, an entire order is listed on one row with multiple items added into one cell. What I need is to have each product on its own row; for example, if someone orders three different products Zapier would create three new rows. This functionality exists when directly exporting orders from BigCommerce, but the "Zap" does not use the BigCommerce export function when pulling order information from my store to the Google Sheet.
I know this is a shot in the dark, but I am hoping someone might have a solution that I can implement. Thank you for your help!
I have created a script that perhaps could be used or modified, at least until you find if the process can be done within Zapier.
You can try the script in the following ss: https://docs.google.com/spreadsheets/d/1ggNYlLEeN3UYtZC_KlOGwpyII9CzOLKMnIOKIDrPJPM/edit?usp=sharing
The script assumes that orders arrive in the tab named Zapier. As things are set up, you would run the script through the Custom Menu.
If there are 2 orders or more, click the menu for each order.
The complete rows appear in the sheet FullList.
(if you want to play/try again, you will have to manually delete the rows in FullList once they are showing).
function processForNewOrders() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sourceSheet = ss.getSheetByName('Zapier');
var destinationSheet = ss.getSheetByName('FullList');
var sourceValues = sourceSheet.getDataRange().getValues();
var destinationValues = destinationSheet.getDataRange().getValues();
var index = [];
destinationValues.forEach( function (x) {
index.push(x[0]);
})
var newOrders = [];
for (var y = sourceValues.length -1 ; y > 0 ; y --){
if(sourceValues[y][0].toString().indexOf('po_number') != -1 ) continue;
var i = index.indexOf(sourceValues[y][0]);
if(i != -1) break; // This readies only the fresh orders for processing
newOrders.push(sourceValues[y]);
}
Logger.log(newOrders)
for (var j = 0 ; j < newOrders.length ; j++){
var output = [];
var orderLine = newOrders[j];
Logger.log('orderLine = ' + orderLine);
var circuit = 0;
var items = 1
while (circuit < items){
var row = [];
for (var z = 0 ; z < orderLine.length; z++){
var cell = orderLine[z];
// Logger.log(cell);
var lines = cell.toString().split(',');
if(lines.length > 1) items = lines.length;
row.push(lines[circuit] ? lines[circuit] : lines[0]);
// Logger.log('row =' + row);
}
circuit ++;
Logger.log('circuit circuit circuit =' + circuit)
output.push(row);
}
}
Logger.log(output);
if(output != undefined)
destinationSheet.getRange(index.length+1,1,output.length,output[0].length).setValues(output);
}
function onOpen() {
var ui = SpreadsheetApp.getUi();
// Or DocumentApp or FormApp.
ui.createMenu('Custom Menu')
.addItem('Process new order', 'processForNewOrders')
.addToUi();
}
I have 30 columns and 1000 rows, I would like to compare column1 with another column. IF the value dont match then I would like to colour it red. Below is a small dataset in my spreadsheet:
A B C D E F ...
1 name sName email
2
3
.
n
Because I have a large dataset and I want to storing my columns in a array, the first row is heading. This is what I have done, however when testing I get empty result, can someone correct me what I am doing wrong?
var index = [];
var sheet = SpreadsheetApp.getActiveSheet();
function col(){
var data = sheet.getDataRange().getValues();
for (var i = 1; i <= data.length; i++) {
te = index[i] = data[1];
Logger.log(columnIndex[i])
if (data[3] != data[7]){
// column_id.setFontColor('red'); <--- I can set the background like this
}
}
}
From the code you can see I am scanning whole spreadsheet data[1] get the heading and in if loop (data[3] != data[7]) compare two columns. I do have to work on my colour variable but that can be done once I get the data that I need.
Try to check this tutorial if it can help you with your problem. This tutorial use a Google AppsScript to compare the two columns. If differences are found, the script should point these out. If no differences are found at all, the script should put out the text "[id]". Just customize this code for your own function.
Here is the code used to achieve this kind of comparison
function stringComparison(s1, s2) {
// lets test both variables are the same object type if not throw an error
if (Object.prototype.toString.call(s1) !== Object.prototype.toString.call(s2)){
throw("Both values need to be an array of cells or individual cells")
}
// if we are looking at two arrays of cells make sure the sizes match and only one column wide
if( Object.prototype.toString.call(s1) === '[object Array]' ) {
if (s1.length != s2.length || s1[0].length > 1 || s2[0].length > 1){
throw("Arrays of cells need to be same size and 1 column wide");
}
// since we are working with an array intialise the return
var out = [];
for (r in s1){ // loop over the rows and find differences using diff sub function
out.push([diff(s1[r][0], s2[r][0])]);
}
return out; // return response
} else { // we are working with two cells so return diff
return diff(s1, s2)
}
}
function diff (s1, s2){
var out = "[ ";
var notid = false;
// loop to match each character
for (var n = 0; n < s1.length; n++){
if (s1.charAt(n) == s2.charAt(n)){
out += "–";
} else {
out += s2.charAt(n);
notid = true;
}
out += " ";
}
out += " ]"
return (notid) ? out : "[ id. ]"; // if notid(entical) return output or [id.]
}
For more information, just check the tutorial link above and this SO question on how to compare two Spreadsheets.
i wanna ask how to change title in
name
so i want to make link name copy to title automatic
so if i make this code
title link
to
title link
how to do that in php or javascript
i know some in php
but need to make all words in link at database or make for every link variable $
can some one help me in that?
I'd suggest:
function textToTitle(elem, attr) {
if (!elem || !attr) {
// if function's called without an element/node,
// or without a string (an attribute such as 'title',
// 'data-customAttribute', etc...) then returns false and quits
return false;
}
else {
// if elem is a node use that node, otherwise assume it's a
// a string containing the id of an element, search for that element
// and use that
elem = elem.nodeType == 1 ? elem : document.getElementById(elem);
// gets the text of the element (innerText for IE)
var text = elem.textContent || elem.innerText;
// sets the attribute
elem.setAttribute(attr, text);
}
}
var link = document.getElementsByTagName('a');
for (var i = 0, len = link.length; i < len; i++) {
textToTitle(link[i], 'title');
}
JS Fiddle demo.
And since it seems traditional to offer a concise jQuery option:
$('a').attr('title', function() { return $(this).text(); });
JS Fiddle demo.
If you don't want to use a library:
var allLinks = document.getElementsByTagName('a');
for(var i = 0; i < allLinks.length; i++){
allLinks[i].title = allLinks[i].innerHTML;
}
Since you wanted to do all this to one element on the page, consider using something like this:
var allLinks = document.getElementById('myelement').getElementsByTagName('a'); // gets all the link elements out of #myelement
for ( int i = 0; i < allLinks.length; i++ ){
allLinks[i].title = allLinks[i].innerHTML;
}
Actually, this is roughly the same as before but we are changing the input elements.
Or, assuming you use jQuery, you could do something like this:
$('a').each(function(){ // runs through each link element on the page
$(this).attr('title', $(this).html()); // and changes the title to the text within itself ($(this).html())
});
In JQuery you can change an attribute by knowing the current tag and using the .attr() feature. Something like $('a').attr('title', 'new_title'); http://api.jquery.com/attr/
Is it possible to filter numbers from the variable.
I can show you one example here from the link http://jsfiddle.net/sweetmaanu/82r5v/6/
I need to get only numbers from the alert message
Simply replace the box string out of it.
DEMO
for (var i = 0; i < order.length; i++) {
order[i] = order[i].replace('box', '');
}
So instead of box1, box2, box3, box4 you want to see 1,2,3,4
You can use a regular expression like this:
var order = $("#boxes").sortable("toArray") + "";
alert(order.replace(/[^0-9,]/g, ''));
I also had to append an empty string to order because it wasn't being recognized as a string object even though the jQuery documentation says it should be when you call sortable("toArray").
change var order = $("#boxes").sortable("toArray");
to var order = $("#boxes").sortable("toArray").join(',').replace(/[a-zA-Z]/gi, "");
Demo: http://jsfiddle.net/82r5v/13/
// Remove all non-digits from the string
'box1'.replace(/\D/g, ''); // => '1'
// Same, but try to make the string a number
Number('box1'.replace(/\D/g, '')); // => 1
// Shorthand for making an object a number (+o is the same as Number(o))
+'box1'.replace(/\D/g, ''); // => 1
// parseInt(s) works if the number is at the beginning
parseInt('1box'); // => 1
// but not if it occurs later
parseInt('box1'); // => NaN
Maybe using regular expressions something like this:
`alert(order.join(',').match(/\d/g));`
To return the array as numbers.
(\d matches all digits, g signifies a global match wildcard)
One way to do it by using regular expressions - http://jsfiddle.net/holodoc/82r5v/14/
$(document).ready(function() {
var arrValuesForOrder = ["2", "1", "3", "4"];
var ul = $("#boxes"),
items = $("#boxes li.con");
for (var i = arrValuesForOrder[arrValuesForOrder.length - 1]; i >= 0; i--) {
// arrValuesForOrder[i] element to move
// i = index to move element at
ul.prepend(items.get(arrValuesForOrder[i] - 1));
}
$("#boxes").sortable({
handle : '.drag',
update: function() {
var order = $("#boxes").sortable("toArray");
var sorted = [];
$.each(order, function(index, value){
sorted.push(value.match(/box(\d+)/)[1]);
})
alert(sorted);
}
});
});